<commit_before>use std::{iter, local_data, num, uint};
use std::iter::MultiplicativeIterator;
use std::cell::RefCell;
use std::rc::Rc;
use std::local_data::Key;

use num::Integer;

use data::monoid::{Sum, MergeMonoidIterator, MergeMultiMonoidIterator, Wrap};

static PRIMES_BELOW100: &'static [uint] = &[
    2,  3,  5,  7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
    43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97
];

struct PrimeInner {
    data: ~[uint]
}

impl PrimeInner {
    #[inline]
    fn new() -> PrimeInner { PrimeInner { data: PRIMES_BELOW100.to_owned() } }

    #[inline]
    fn max_prime(&self) -> uint { *self.data.last().unwrap() }

    #[inline]
    fn nth(&mut self, n: uint) -> uint { self.grow(n + 1); self.data[n] }

    #[inline]
    fn contains(&mut self, n: uint) -> bool {
        if n < self.max_prime() { return self.data.bsearch_elem(&n).is_some() }

        if !self.is_coprime(n) { return false }

        iter::count(self.data.len(), 1)
            .map(|i| self.nth(i))
            .take_while(|&p| p * p <= n)
            .all(|p| !n.divides(&p))
    }

    #[inline]
    fn is_coprime(&self, n: uint) -> bool {
        self.data.iter()
            .take_while(|& &p| p * p <= n)
            .all(|&p| !n.divides(&p))
    }

    #[inline]
    fn grow(&mut self, len: uint) {
        if self.data.len() >= len { return }

        for n in iter::count(self.max_prime() + 2, 2) {
            if self.is_coprime(n) { self.data.push(n); }
            if self.data.len() >= len { return }
        }
    }
}

static TASK_PRIME_KEY: Key<Prime> = &Key;

#[deriving(Clone)]
pub struct Prime {
    priv data: Rc<RefCell<PrimeInner>>
}

impl Prime {
    #[inline]
    pub fn new() -> Prime {
        let prime = local_data::get_mut(TASK_PRIME_KEY, |val| match val {
                Some(prime) => Some(prime.clone()),
                None        => None
            });

        match prime {
            Some(prime) => prime,
            None => {
                let prime = Prime::new_empty();
                local_data::set(TASK_PRIME_KEY, prime.clone());
                prime
            }
        }
    }
    #[inline]
    fn new_empty() -> Prime { Prime { data: Rc::new(RefCell::new(PrimeInner::new())) } }
    #[inline]
    pub fn nth(&self, n: uint) -> uint { self.data.deref().with_mut(|p| p.nth(n)) }
    #[inline]
    pub fn contains(&self, n: uint) -> bool { self.data.deref().with_mut(|p| p.contains(n)) }

    #[inline]
    pub fn iter<'a>(&'a self) -> PrimeIterator { PrimeIterator { idx: 0, data: self.data.clone() } }
    #[inline]
    pub fn factorize(&self, n: uint) -> FactorizeIterator {
        FactorizeIterator { num: n, iter: self.iter() }
    }
    #[inline]
    pub fn num_of_divisor(&self, n: uint) -> uint {
        if n == 0 { return 0 }
        self.factorize(n)
            .map(|(_base, exp)| (exp as uint) + 1)
            .product()
    }
    #[inline]
    pub fn sum_of_divisor(&self, n: uint) -> uint {
        if n == 0 { return 0 }
        self.factorize(n)
            .map(|(base, exp)| (num::pow(base, (exp as uint) + 1) - 1) / (base - 1) )
            .product()
    }
    #[inline]
    pub fn num_of_proper_divisor(&self, n: uint) -> uint { self.num_of_divisor(n) - 1 }
    #[inline]
    pub fn sum_of_proper_divisor(&self, n: uint) -> uint { self.sum_of_divisor(n) - n }
    #[inline]
    pub fn comb(&self, n: uint, r: uint) -> uint {
        let ns = range(r + 1, n + 1)
            .map(|n| {
                self.factorize(n)
                    .map(|(base, exp)| (base, Sum(exp)))
            }).to_owned_vec();
        let numer = MergeMultiMonoidIterator::new(ns);

        let ds = range(1, n - r + 1)
            .map(|n| {
                self.factorize(n)
                    .map(|(base, exp)| (base, Sum(-exp)))
            }).to_owned_vec();
        let denom = MergeMultiMonoidIterator::new(ds);

        MergeMonoidIterator::new(numer, denom).map(|(a, m)| (a, m.unwrap())).to_uint()
    }
}

pub struct PrimeIterator {
    priv idx: uint,
    priv data: Rc<RefCell<PrimeInner>>
}

impl Iterator<uint> for PrimeIterator {
    #[inline]
    fn next(&mut self) -> Option<uint> {
        let p = self.data.deref().with_mut(|p| p.nth(self.idx));
        self.idx += 1;
        Some(p)
    }
}

impl RandomAccessIterator<uint> for PrimeIterator {
    #[inline]
    fn indexable(&self) -> uint { uint::MAX }

    #[inline]
    fn idx(&self, index: uint) -> Option<uint> {
        let p = self.data.deref().with_mut(|p| p.nth(index));
        Some(p)
    }
}

pub type Factor = (uint, int);

pub struct FactorizeIterator {
    priv num: uint,
    priv iter: PrimeIterator
}

impl Iterator<Factor> for FactorizeIterator {
    #[inline]
    fn next(&mut self) -> Option<Factor> {
        if self.num <= 1 { return None }

        for p in self.iter {
            if p * p > self.num {
                let n = self.num;
                self.num = 1;
                return Some((n, 1))
            }

            if self.num.divides(&p) {
                let mut exp = 1;
                self.num /= p;

                while self.num.divides(&p) {
                    exp += 1;
                    self.num /= p;
                }
                return Some((p, exp))
            }
        }

        unreachable!()
    }
}

pub trait FactorIterator {
    fn to_uint(&mut self) -> uint;
}

impl<IA: Iterator<Factor>> FactorIterator for IA {
    #[inline]
    fn to_uint(&mut self) -> uint {
        self.fold(1, |s, (base, exp)| {
                if exp > 0 {
                    s * num::pow(base, exp as uint)
                } else {
                    s / num::pow(base, (-exp) as uint)
                }
            })
    }
}

#[cfg(test)]
mod tests {
    use super::{Prime, Factor, FactorIterator};

    static PRIMES_BELOW200: &'static [uint] = &[
        2,  3,  5,  7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
        43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
        101, 103, 107, 109, 113, 127, 131, 137, 139, 149,
        151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199
            ];

    #[test]
    fn iter() {
        let prime = Prime::new();
        assert_eq!(PRIMES_BELOW200.to_owned(), prime.iter().take(PRIMES_BELOW200.len()).to_owned_vec());
    }

    #[test]
    fn nth() {
        let prime = Prime::new_empty();
        // Generated primes
        for (i, &p) in PRIMES_BELOW200.iter().enumerate() {
            assert_eq!(p, prime.nth(i));
        }
        // Memoized primes
        for (i, &p) in PRIMES_BELOW200.iter().enumerate() {
            assert_eq!(p, prime.nth(i));
        }
    }

    #[test]
    fn contains() {
        let prime = Prime::new();
        assert!(!prime.contains(0));
        assert!(!prime.contains(1));
        assert!(prime.contains(2));
        assert!(prime.contains(3));
        assert!(!prime.contains(4));
        assert!(prime.contains(5));
        assert!(!prime.contains(6));
        assert!(prime.contains(7));
        assert!(!prime.contains(100));
    }

    #[test]
    fn multi_iter() {
        let prime = Prime::new();
        for _p1 in prime.iter() {
            for _p2 in prime.iter() {
                break;
            }
            break;
        }
    }

    #[test]
    fn clone_clones_data() {
        let p1 = Prime::new();
        let p2 = p1.clone();
        p1.nth(500);
        let l1 = p1.data.with(|p| p.data.len());
        let l2 = p2.data.with(|p| p.data.len());
        assert_eq!(l1, l2);
    }

    #[test]
    fn factorize() {
        fn check(n: uint, fs: ~[Factor]) {
            let ps = Prime::new();
            assert_eq!(fs, ps.factorize(n).to_owned_vec());
            if n != 0 {
                assert_eq!(n, ps.factorize(n).to_uint());
            }
        }

        check(0, ~[]);
        check(1, ~[]);
        check(2, ~[(2, 1)]);
        check(3, ~[(3, 1)]);
        check(4, ~[(2, 2)]);
        check(5, ~[(5, 1)]);
        check(6, ~[(2, 1), (3, 1)]);
        check(7, ~[(7, 1)]);
        check(8, ~[(2, 3)]);
        check(9, ~[(3, 2)]);
        check(10, ~[(2, 1), (5, 1)]);

        check(8 * 27, ~[(2, 3), (3, 3)]);
        check(97, ~[(97, 1)]);
        check(97 * 41, ~[(41, 1), (97, 1)]);
    }

    #[test]
    fn num_of_divisor() {
        let pairs = [
            (0, 0),
            (1, 1), (2, 2), (3, 2), (4, 3), (5, 2), (6, 4),
            (7, 2), (8, 4), (9, 3), (10, 4), (11, 2), (12, 6),
            (24, 8), (36, 9), (48, 10), (60, 12),
            (50, 6)
            ];
        let p = Prime::new();
        for &(n, num_div) in pairs.iter() {
            assert_eq!(num_div, p.num_of_divisor(n));
        }
    }

    #[test]
    fn sum_of_divisor() {
        let pairs = [
            (0, 0),
            (1, 1), (2, 3), (3, 4), (4, 7), (5, 6), (6, 12),
            (7, 8), (8, 15), (9, 13), (10, 18), (11, 12), (12, 28),
            (24, 60), (36, 91), (48, 124), (60, 168),
            (50, 93)
            ];
        let p = Prime::new();
        for &(n, sum_div) in pairs.iter() {
            assert_eq!(sum_div, p.sum_of_divisor(n));
        }
    }

    #[test]
    fn comb() {
        let prime = Prime::new();
        assert_eq!(1, prime.comb(2, 2));
        assert_eq!(3, prime.comb(3, 2));
        assert_eq!(6, prime.comb(4, 2));
        assert_eq!(10, prime.comb(5, 2));

        assert_eq!(137846528820, prime.comb(40, 20));
    }
}

#[cfg(test)]
mod bench {
    use super::Prime;
    use test::BenchHarness;

    #[bench]
    fn get_5000th(bh: &mut BenchHarness) {
        bh.iter(|| { Prime::new().nth(5000); });
    }
    #[bench]
    fn get_5000th_nocache(bh: &mut BenchHarness) {
        bh.iter(|| { Prime::new_empty().nth(5000); });
    }

    #[bench]
    fn get_below_5000th(bh: &mut BenchHarness) {
        bh.iter(|| {
                let prime = Prime::new();
                for _p in prime.iter().take(5000) {}
            });
    }
    #[bench]
    fn get_below_5000th_nocache(bh: &mut BenchHarness) {
        bh.iter(|| {
                let prime = Prime::new_empty();
                for _p in prime.iter().take(5000) {}
            });
    }

    #[bench]
    fn factorial_600851475143(bh: &mut BenchHarness) {
        bh.iter(|| {
                let ps = Prime::new();
                ps.factorize(600851475143).fold(0, |a, (b, _)| a + b);
            });
    }

    #[bench]
    fn factorial_600851475143_nocache(bh: &mut BenchHarness) {
        bh.iter(|| {
                let ps = Prime::new_empty();
                ps.factorize(600851475143).fold(0, |a, (b, _)| a + b);
            });
    }
}
<commit_msg>remove with/with_mut<commit_after>use std::{iter, local_data, num, uint};
use std::iter::MultiplicativeIterator;
use std::cell::RefCell;
use std::rc::Rc;
use std::local_data::Key;

use num::Integer;

use data::monoid::{Sum, MergeMonoidIterator, MergeMultiMonoidIterator, Wrap};

static PRIMES_BELOW100: &'static [uint] = &[
    2,  3,  5,  7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
    43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97
];

struct PrimeInner {
    data: ~[uint]
}

impl PrimeInner {
    #[inline]
    fn new() -> PrimeInner { PrimeInner { data: PRIMES_BELOW100.to_owned() } }

    #[inline]
    fn max_prime(&self) -> uint { *self.data.last().unwrap() }

    #[inline]
    fn nth(&mut self, n: uint) -> uint { self.grow(n + 1); self.data[n] }

    #[inline]
    fn contains(&mut self, n: uint) -> bool {
        if n < self.max_prime() { return self.data.bsearch_elem(&n).is_some() }

        if !self.is_coprime(n) { return false }

        iter::count(self.data.len(), 1)
            .map(|i| self.nth(i))
            .take_while(|&p| p * p <= n)
            .all(|p| !n.divides(&p))
    }

    #[inline]
    fn is_coprime(&self, n: uint) -> bool {
        self.data.iter()
            .take_while(|& &p| p * p <= n)
            .all(|&p| !n.divides(&p))
    }

    #[inline]
    fn grow(&mut self, len: uint) {
        if self.data.len() >= len { return }

        for n in iter::count(self.max_prime() + 2, 2) {
            if self.is_coprime(n) { self.data.push(n); }
            if self.data.len() >= len { return }
        }
    }
}

static TASK_PRIME_KEY: Key<Prime> = &Key;

#[deriving(Clone)]
pub struct Prime {
    priv data: Rc<RefCell<PrimeInner>>
}

impl Prime {
    #[inline]
    pub fn new() -> Prime {
        let prime = local_data::get_mut(TASK_PRIME_KEY, |val| match val {
                Some(prime) => Some(prime.clone()),
                None        => None
            });

        match prime {
            Some(prime) => prime,
            None => {
                let prime = Prime::new_empty();
                local_data::set(TASK_PRIME_KEY, prime.clone());
                prime
            }
        }
    }
    #[inline]
    fn new_empty() -> Prime { Prime { data: Rc::new(RefCell::new(PrimeInner::new())) } }
    #[inline]
    pub fn nth(&self, n: uint) -> uint { self.data.borrow_mut().nth(n) }
    #[inline]
    pub fn contains(&self, n: uint) -> bool { self.data.borrow_mut().contains(n) }

    #[inline]
    pub fn iter<'a>(&'a self) -> PrimeIterator { PrimeIterator { idx: 0, data: self.data.clone() } }
    #[inline]
    pub fn factorize(&self, n: uint) -> FactorizeIterator {
        FactorizeIterator { num: n, iter: self.iter() }
    }
    #[inline]
    pub fn num_of_divisor(&self, n: uint) -> uint {
        if n == 0 { return 0 }
        self.factorize(n)
            .map(|(_base, exp)| (exp as uint) + 1)
            .product()
    }
    #[inline]
    pub fn sum_of_divisor(&self, n: uint) -> uint {
        if n == 0 { return 0 }
        self.factorize(n)
            .map(|(base, exp)| (num::pow(base, (exp as uint) + 1) - 1) / (base - 1) )
            .product()
    }
    #[inline]
    pub fn num_of_proper_divisor(&self, n: uint) -> uint { self.num_of_divisor(n) - 1 }
    #[inline]
    pub fn sum_of_proper_divisor(&self, n: uint) -> uint { self.sum_of_divisor(n) - n }
    #[inline]
    pub fn comb(&self, n: uint, r: uint) -> uint {
        let ns = range(r + 1, n + 1)
            .map(|n| {
                self.factorize(n)
                    .map(|(base, exp)| (base, Sum(exp)))
            }).to_owned_vec();
        let numer = MergeMultiMonoidIterator::new(ns);

        let ds = range(1, n - r + 1)
            .map(|n| {
                self.factorize(n)
                    .map(|(base, exp)| (base, Sum(-exp)))
            }).to_owned_vec();
        let denom = MergeMultiMonoidIterator::new(ds);

        MergeMonoidIterator::new(numer, denom).map(|(a, m)| (a, m.unwrap())).to_uint()
    }
}

pub struct PrimeIterator {
    priv idx: uint,
    priv data: Rc<RefCell<PrimeInner>>
}

impl Iterator<uint> for PrimeIterator {
    #[inline]
    fn next(&mut self) -> Option<uint> {
        let p = self.data.borrow_mut().nth(self.idx);
        self.idx += 1;
        Some(p)
    }
}

impl RandomAccessIterator<uint> for PrimeIterator {
    #[inline]
    fn indexable(&self) -> uint { uint::MAX }

    #[inline]
    fn idx(&self, index: uint) -> Option<uint> {
        Some(self.data.borrow_mut().nth(index))
    }
}

pub type Factor = (uint, int);

pub struct FactorizeIterator {
    priv num: uint,
    priv iter: PrimeIterator
}

impl Iterator<Factor> for FactorizeIterator {
    #[inline]
    fn next(&mut self) -> Option<Factor> {
        if self.num <= 1 { return None }

        for p in self.iter {
            if p * p > self.num {
                let n = self.num;
                self.num = 1;
                return Some((n, 1))
            }

            if self.num.divides(&p) {
                let mut exp = 1;
                self.num /= p;

                while self.num.divides(&p) {
                    exp += 1;
                    self.num /= p;
                }
                return Some((p, exp))
            }
        }

        unreachable!()
    }
}

pub trait FactorIterator {
    fn to_uint(&mut self) -> uint;
}

impl<IA: Iterator<Factor>> FactorIterator for IA {
    #[inline]
    fn to_uint(&mut self) -> uint {
        self.fold(1, |s, (base, exp)| {
                if exp > 0 {
                    s * num::pow(base, exp as uint)
                } else {
                    s / num::pow(base, (-exp) as uint)
                }
            })
    }
}

#[cfg(test)]
mod tests {
    use super::{Prime, Factor, FactorIterator};

    static PRIMES_BELOW200: &'static [uint] = &[
        2,  3,  5,  7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
        43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
        101, 103, 107, 109, 113, 127, 131, 137, 139, 149,
        151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199
            ];

    #[test]
    fn iter() {
        let prime = Prime::new();
        assert_eq!(PRIMES_BELOW200.to_owned(), prime.iter().take(PRIMES_BELOW200.len()).to_owned_vec());
    }

    #[test]
    fn nth() {
        let prime = Prime::new_empty();
        // Generated primes
        for (i, &p) in PRIMES_BELOW200.iter().enumerate() {
            assert_eq!(p, prime.nth(i));
        }
        // Memoized primes
        for (i, &p) in PRIMES_BELOW200.iter().enumerate() {
            assert_eq!(p, prime.nth(i));
        }
    }

    #[test]
    fn contains() {
        let prime = Prime::new();
        assert!(!prime.contains(0));
        assert!(!prime.contains(1));
        assert!(prime.contains(2));
        assert!(prime.contains(3));
        assert!(!prime.contains(4));
        assert!(prime.contains(5));
        assert!(!prime.contains(6));
        assert!(prime.contains(7));
        assert!(!prime.contains(100));
    }

    #[test]
    fn multi_iter() {
        let prime = Prime::new();
        for _p1 in prime.iter() {
            for _p2 in prime.iter() {
                break;
            }
            break;
        }
    }

    #[test]
    fn clone_clones_data() {
        let p1 = Prime::new();
        let p2 = p1.clone();
        p1.nth(500);
        let l1 = p1.data.borrow().data.len();
        let l2 = p2.data.borrow().data.len();
        assert_eq!(l1, l2);
    }

    #[test]
    fn factorize() {
        fn check(n: uint, fs: ~[Factor]) {
            let ps = Prime::new();
            assert_eq!(fs, ps.factorize(n).to_owned_vec());
            if n != 0 {
                assert_eq!(n, ps.factorize(n).to_uint());
            }
        }

        check(0, ~[]);
        check(1, ~[]);
        check(2, ~[(2, 1)]);
        check(3, ~[(3, 1)]);
        check(4, ~[(2, 2)]);
        check(5, ~[(5, 1)]);
        check(6, ~[(2, 1), (3, 1)]);
        check(7, ~[(7, 1)]);
        check(8, ~[(2, 3)]);
        check(9, ~[(3, 2)]);
        check(10, ~[(2, 1), (5, 1)]);

        check(8 * 27, ~[(2, 3), (3, 3)]);
        check(97, ~[(97, 1)]);
        check(97 * 41, ~[(41, 1), (97, 1)]);
    }

    #[test]
    fn num_of_divisor() {
        let pairs = [
            (0, 0),
            (1, 1), (2, 2), (3, 2), (4, 3), (5, 2), (6, 4),
            (7, 2), (8, 4), (9, 3), (10, 4), (11, 2), (12, 6),
            (24, 8), (36, 9), (48, 10), (60, 12),
            (50, 6)
            ];
        let p = Prime::new();
        for &(n, num_div) in pairs.iter() {
            assert_eq!(num_div, p.num_of_divisor(n));
        }
    }

    #[test]
    fn sum_of_divisor() {
        let pairs = [
            (0, 0),
            (1, 1), (2, 3), (3, 4), (4, 7), (5, 6), (6, 12),
            (7, 8), (8, 15), (9, 13), (10, 18), (11, 12), (12, 28),
            (24, 60), (36, 91), (48, 124), (60, 168),
            (50, 93)
            ];
        let p = Prime::new();
        for &(n, sum_div) in pairs.iter() {
            assert_eq!(sum_div, p.sum_of_divisor(n));
        }
    }

    #[test]
    fn comb() {
        let prime = Prime::new();
        assert_eq!(1, prime.comb(2, 2));
        assert_eq!(3, prime.comb(3, 2));
        assert_eq!(6, prime.comb(4, 2));
        assert_eq!(10, prime.comb(5, 2));

        assert_eq!(137846528820, prime.comb(40, 20));
    }
}

#[cfg(test)]
mod bench {
    use super::Prime;
    use test::BenchHarness;

    #[bench]
    fn get_5000th(bh: &mut BenchHarness) {
        bh.iter(|| { Prime::new().nth(5000); });
    }
    #[bench]
    fn get_5000th_nocache(bh: &mut BenchHarness) {
        bh.iter(|| { Prime::new_empty().nth(5000); });
    }

    #[bench]
    fn get_below_5000th(bh: &mut BenchHarness) {
        bh.iter(|| {
                let prime = Prime::new();
                for _p in prime.iter().take(5000) {}
            });
    }
    #[bench]
    fn get_below_5000th_nocache(bh: &mut BenchHarness) {
        bh.iter(|| {
                let prime = Prime::new_empty();
                for _p in prime.iter().take(5000) {}
            });
    }

    #[bench]
    fn factorial_600851475143(bh: &mut BenchHarness) {
        bh.iter(|| {
                let ps = Prime::new();
                ps.factorize(600851475143).fold(0, |a, (b, _)| a + b);
            });
    }

    #[bench]
    fn factorial_600851475143_nocache(bh: &mut BenchHarness) {
        bh.iter(|| {
                let ps = Prime::new_empty();
                ps.factorize(600851475143).fold(0, |a, (b, _)| a + b);
            });
    }
}
<|endoftext|>


<commit_before>extern crate glib;
extern crate cairo;
extern crate cairo_sys;
extern crate libc;

use self::glib::translate::*;

use state::RsvgState;
use path_builder::RsvgPathBuilder;

pub enum RsvgDrawingCtx {}

extern "C" {
    fn rsvg_drawing_ctx_get_dpi (draw_ctx: *const RsvgDrawingCtx,
                                 out_dpi_x: *mut f64,
                                 out_dpi_y: *mut f64);

    fn rsvg_drawing_ctx_get_normalized_font_size (draw_ctx: *const RsvgDrawingCtx) -> f64;

    fn rsvg_drawing_ctx_get_view_box_size (draw_ctx: *const RsvgDrawingCtx,
                                           out_x: *mut f64,
                                           out_y: *mut f64);

    fn rsvg_drawing_ctx_push_view_box (draw_ctx: *const RsvgDrawingCtx,
                                       width:     f64,
                                       height:    f64);

    fn rsvg_drawing_ctx_pop_view_box (draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_state_reinherit_top (draw_ctx: *const RsvgDrawingCtx,
                                 state: *mut RsvgState,
                                 dominate: libc::c_int);

    fn rsvg_render_path_builder (draw_ctx: *const RsvgDrawingCtx,
                                 builder: *const RsvgPathBuilder);

    fn rsvg_cairo_get_cairo_context (draw_ctx: *const RsvgDrawingCtx) -> *mut cairo_sys::cairo_t;
}

pub fn get_dpi (draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
    let mut dpi_x: f64 = 0.0;
    let mut dpi_y: f64 = 0.0;

    unsafe { rsvg_drawing_ctx_get_dpi (draw_ctx, &mut dpi_x, &mut dpi_y); }

    (dpi_x, dpi_y)
}

pub fn get_normalized_font_size (draw_ctx: *const RsvgDrawingCtx) -> f64 {
    unsafe { rsvg_drawing_ctx_get_normalized_font_size (draw_ctx) }
}

pub fn get_view_box_size (draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
    let mut w: f64 = 0.0;
    let mut h: f64 = 0.0;

    unsafe { rsvg_drawing_ctx_get_view_box_size (draw_ctx, &mut w, &mut h); }

    (w, h)
}

pub fn push_view_box (draw_ctx: *const RsvgDrawingCtx,
                      width:     f64,
                      height:    f64)
{
    unsafe { rsvg_drawing_ctx_push_view_box (draw_ctx, width, height); }
}

pub fn pop_view_box (draw_ctx: *const RsvgDrawingCtx) {
    unsafe { rsvg_drawing_ctx_pop_view_box (draw_ctx); }
}

pub fn state_reinherit_top (draw_ctx: *const RsvgDrawingCtx,
                            state: *mut RsvgState,
                            dominate: i32) {
    unsafe { rsvg_state_reinherit_top (draw_ctx, state, dominate); }
}

pub fn render_path_builder (draw_ctx: *const RsvgDrawingCtx,
                            builder: &RsvgPathBuilder)
{
    unsafe { rsvg_render_path_builder (draw_ctx, builder); }
}

pub fn get_cairo_context (draw_ctx: *const RsvgDrawingCtx) -> cairo::Context
{
    unsafe {
        let raw_cr = rsvg_cairo_get_cairo_context (draw_ctx);

        let cr = cairo::Context::from_glib_none (raw_cr);

        cr
    }
}
<commit_msg>drawing_ctx.rs: Wrappers for acquire_node() and release_node()<commit_after>extern crate glib;
extern crate cairo;
extern crate cairo_sys;
extern crate libc;

use self::glib::translate::*;

use state::RsvgState;
use path_builder::RsvgPathBuilder;

pub enum RsvgDrawingCtx {}

pub enum RsvgNode {}

extern "C" {
    fn rsvg_drawing_ctx_get_dpi (draw_ctx: *const RsvgDrawingCtx,
                                 out_dpi_x: *mut f64,
                                 out_dpi_y: *mut f64);

    fn rsvg_drawing_ctx_get_normalized_font_size (draw_ctx: *const RsvgDrawingCtx) -> f64;

    fn rsvg_drawing_ctx_get_view_box_size (draw_ctx: *const RsvgDrawingCtx,
                                           out_x: *mut f64,
                                           out_y: *mut f64);

    fn rsvg_drawing_ctx_push_view_box (draw_ctx: *const RsvgDrawingCtx,
                                       width:     f64,
                                       height:    f64);

    fn rsvg_drawing_ctx_pop_view_box (draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_drawing_ctx_acquire_node (draw_ctx: *const RsvgDrawingCtx,
                                      url:      *const libc::c_char) -> *mut RsvgNode;

    fn rsvg_drawing_ctx_release_node (draw_ctx: *const RsvgDrawingCtx,
                                      node:     *mut RsvgNode);

    fn rsvg_state_reinherit_top (draw_ctx: *const RsvgDrawingCtx,
                                 state: *mut RsvgState,
                                 dominate: libc::c_int);

    fn rsvg_render_path_builder (draw_ctx: *const RsvgDrawingCtx,
                                 builder: *const RsvgPathBuilder);

    fn rsvg_cairo_get_cairo_context (draw_ctx: *const RsvgDrawingCtx) -> *mut cairo_sys::cairo_t;
}

pub fn get_dpi (draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
    let mut dpi_x: f64 = 0.0;
    let mut dpi_y: f64 = 0.0;

    unsafe { rsvg_drawing_ctx_get_dpi (draw_ctx, &mut dpi_x, &mut dpi_y); }

    (dpi_x, dpi_y)
}

pub fn get_normalized_font_size (draw_ctx: *const RsvgDrawingCtx) -> f64 {
    unsafe { rsvg_drawing_ctx_get_normalized_font_size (draw_ctx) }
}

pub fn get_view_box_size (draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
    let mut w: f64 = 0.0;
    let mut h: f64 = 0.0;

    unsafe { rsvg_drawing_ctx_get_view_box_size (draw_ctx, &mut w, &mut h); }

    (w, h)
}

pub fn push_view_box (draw_ctx: *const RsvgDrawingCtx,
                      width:     f64,
                      height:    f64)
{
    unsafe { rsvg_drawing_ctx_push_view_box (draw_ctx, width, height); }
}

pub fn pop_view_box (draw_ctx: *const RsvgDrawingCtx) {
    unsafe { rsvg_drawing_ctx_pop_view_box (draw_ctx); }
}

pub fn acquire_node (draw_ctx: *const RsvgDrawingCtx,
                     url:      &str) -> *mut RsvgNode {
    unsafe { rsvg_drawing_ctx_acquire_node (draw_ctx, str::to_glib_none (url).0) }
}

pub fn release_node (draw_ctx: *const RsvgDrawingCtx,
                     node:     *mut RsvgNode) {
    unsafe { rsvg_drawing_ctx_release_node (draw_ctx, node); }
}

pub fn state_reinherit_top (draw_ctx: *const RsvgDrawingCtx,
                            state: *mut RsvgState,
                            dominate: i32) {
    unsafe { rsvg_state_reinherit_top (draw_ctx, state, dominate); }
}

pub fn render_path_builder (draw_ctx: *const RsvgDrawingCtx,
                            builder: &RsvgPathBuilder)
{
    unsafe { rsvg_render_path_builder (draw_ctx, builder); }
}

pub fn get_cairo_context (draw_ctx: *const RsvgDrawingCtx) -> cairo::Context
{
    unsafe {
        let raw_cr = rsvg_cairo_get_cairo_context (draw_ctx);

        let cr = cairo::Context::from_glib_none (raw_cr);

        cr
    }
}
<|endoftext|>


<commit_before>use time::now_utc;
use std::io::{File, Open, ReadWrite};
use postgres::Connection;
use std::collections::hash_map::HashMap;

pub fn gen_timecode() -> String {
    now_utc().strftime("%y%m%d%H%M%S").unwrap().to_string()
}

pub fn gen_full_name(name: &str) -> String {
    format!("_{}_{}", gen_timecode(), name)
}

pub fn create_migration_file(name: &str, base_path: Path) -> String {
    let full_name = gen_full_name(name);
    let final_path = base_path.join(format!("{}.rs", full_name));

    let mut file = match File::open_mode(&final_path, Open, ReadWrite) {
        Ok(f) => f,
        Err(e) => panic!("file error: {}", e),
    };

    file.write(b"").unwrap();
    full_name
}

pub trait RawMigration<Conn> {
    fn version(&self) -> u64;
    fn up(&self, cn: &Conn);
    fn down(&self, cn: &Conn);
}

pub type Migrations = Vec<Box<RawMigration<Connection> + 'static>>;
pub type MigrationRefs<'a> = Vec<&'a Box<RawMigration<Connection> + 'static>>;

pub fn ensure_schema_migrations(cn: &Connection) {
    cn.execute("CREATE TABLE IF NOT EXISTS schema_migrations (
         version BIGINT NOT NULL
    );", &[]).unwrap();
}

pub fn insert_version(version: &i64, cn: &Connection) {
    cn.execute("INSERT INTO schema_migrations VALUES ($1);", &[version]).unwrap();
}

pub fn delete_version(version: &i64, cn: &Connection) {
    cn.execute("DELETE FROM schema_migrations WHERE version = $1;", &[version]).unwrap();
}

pub fn get_versions_as_hash(cn: &Connection) -> HashMap<i64, bool> {
    let stmt = cn.prepare("SELECT version FROM schema_migrations ORDER BY version desc;").unwrap();
    let mut rows = stmt.query(&[]).unwrap();
    let mut db_versions: HashMap<i64, bool> = HashMap::new();

    for row in rows {
        db_versions.insert(row.get(0), true);
    }

    db_versions
}

pub fn get_versions_as_vec(cn: &Connection) -> Vec<i64> {
    let stmt = cn.prepare("SELECT version FROM schema_migrations ORDER BY version desc;").unwrap();
    let mut rows = stmt.query(&[]).unwrap();
    let mut db_versions: Vec<i64> = vec![];

    for row in rows {
        db_versions.push(row.get(0));
    }

    db_versions
}

pub fn run(migrations: &Migrations, cn: &Connection) {
    ensure_schema_migrations(cn);
    let db_versions = get_versions_as_hash(cn);

    let migrations_to_run: MigrationRefs = migrations.iter().filter(|m| {
        let version = m.version().to_i64().unwrap();
        !db_versions.contains_key(&version)
    }).collect();

    for migration in migrations_to_run.iter() {
        migration.up(cn);
        insert_version(&migration.version().to_i64().unwrap(), cn);

        println!("Migration completed: {}", migration.version());
    }
}

pub fn rollback(steps: uint, migrations: &Migrations, cn: &Connection) {
    ensure_schema_migrations(cn);
    let db_versions = get_versions_as_vec(cn);
    let db_versions_to_run = db_versions.slice(0, steps);

    let migrations_to_run: MigrationRefs = migrations.iter().filter(|m| {
        let version = m.version().to_i64().unwrap();
        db_versions_to_run.contains(&version)
    }).collect();

    for migration in migrations_to_run.iter() {
        migration.down(cn);
        delete_version(&migration.version().to_i64().unwrap(), cn);

        println!("Migration reverted: {}", migration.version());
    }
}<commit_msg>feat: wrap `RawMigration` with `Migration`<commit_after>use time::now_utc;
use std::io::{File, Open, ReadWrite};
use postgres::Connection;
use std::collections::hash_map::HashMap;

pub fn gen_timecode() -> String {
    now_utc().strftime("%y%m%d%H%M%S").unwrap().to_string()
}

pub fn gen_full_name(name: &str) -> String {
    format!("_{}_{}", gen_timecode(), name)
}

pub fn create_migration_file(name: &str, base_path: Path) -> String {
    let full_name = gen_full_name(name);
    let final_path = base_path.join(format!("{}.rs", full_name));

    let mut file = match File::open_mode(&final_path, Open, ReadWrite) {
        Ok(f) => f,
        Err(e) => panic!("file error: {}", e),
    };

    file.write(b"").unwrap();
    full_name
}

pub struct Migration<Conn> {
    version: u64,
    name: String,
    raw: Box<RawMigration<Conn> + 'static>
}

impl<Conn> Migration<Conn> {
    pub fn new(version: u64, name: &str, raw: Box<RawMigration<Conn> + 'static>) -> Migration<Conn> {
        Migration {
            version: version,
            name: name.to_string(),
            raw: raw
        }
    }

    pub fn version(&self) -> &u64 { &self.version }
    pub fn name(&self) -> &str { self.name.as_slice() }
    pub fn raw(&self) -> &Box<RawMigration<Conn> + 'static> { &self.raw }
}

pub trait RawMigration<Conn> {
    fn up(&self, cn: &Conn);
    fn down(&self, cn: &Conn);
}

pub type Migrations = Vec<Box<Migration<Connection>>>;
pub type MigrationRefs<'a> = Vec<&'a Box<Migration<Connection>>>;

pub fn ensure_schema_migrations(cn: &Connection) {
    cn.execute("CREATE TABLE IF NOT EXISTS schema_migrations (
         version BIGINT NOT NULL
    );", &[]).unwrap();
}

pub fn insert_version(version: &i64, cn: &Connection) {
    cn.execute("INSERT INTO schema_migrations VALUES ($1);", &[version]).unwrap();
}

pub fn delete_version(version: &i64, cn: &Connection) {
    cn.execute("DELETE FROM schema_migrations WHERE version = $1;", &[version]).unwrap();
}

pub fn get_versions_as_hash(cn: &Connection) -> HashMap<i64, bool> {
    let stmt = cn.prepare("SELECT version FROM schema_migrations ORDER BY version desc;").unwrap();
    let mut rows = stmt.query(&[]).unwrap();
    let mut db_versions: HashMap<i64, bool> = HashMap::new();

    for row in rows {
        db_versions.insert(row.get(0), true);
    }

    db_versions
}

pub fn get_versions_as_vec(cn: &Connection) -> Vec<i64> {
    let stmt = cn.prepare("SELECT version FROM schema_migrations ORDER BY version desc;").unwrap();
    let mut rows = stmt.query(&[]).unwrap();
    let mut db_versions: Vec<i64> = vec![];

    for row in rows {
        db_versions.push(row.get(0));
    }

    db_versions
}

pub fn run(migrations: &Migrations, cn: &Connection) {
    ensure_schema_migrations(cn);
    let db_versions = get_versions_as_hash(cn);

    let migrations_to_run: MigrationRefs = migrations.iter().filter(|m| {
        let version = m.version().to_i64().unwrap();
        !db_versions.contains_key(&version)
    }).collect();

    for migration in migrations_to_run.iter() {
        migration.raw().up(cn);
        insert_version(&migration.version().to_i64().unwrap(), cn);

        println!("Migration completed: {} {}", migration.version(), migration.name());
    }
}

pub fn rollback(steps: uint, migrations: &Migrations, cn: &Connection) {
    ensure_schema_migrations(cn);
    let db_versions = get_versions_as_vec(cn);
    let db_versions_to_run = db_versions.slice(0, steps);

    let migrations_to_run: MigrationRefs = migrations.iter().filter(|m| {
        let version = m.version().to_i64().unwrap();
        db_versions_to_run.contains(&version)
    }).collect();

    for migration in migrations_to_run.iter() {
        migration.raw().down(cn);
        delete_version(&migration.version().to_i64().unwrap(), cn);

        println!("Migration reverted: {} {}", migration.version(), migration.name());
    }
}<|endoftext|>


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

pub mod generic;

use std::io;
use std::fmt;

use std::error::Error as ErrorTrait;
use std::fmt::{Display, Formatter};
use std::str::FromStr;
use std::time::Duration;

use net;

use net::url::Url;

use timer::DEFAULT_TIMER;

use self::generic::HeaderField;
use self::generic::ClientCodec as GenericClientCodec;
use self::generic::Request as GenericRequest;
use self::generic::Response as GenericResponse;
use self::generic::RequestBuilder as GenericRequestBuilder;

use bytes::BytesMut;

use futures::{Future, Poll, Sink, Stream};

use tokio_core::net::TcpStream;
use tokio_core::reactor::Handle as TokioHandle;

use tokio_io::AsyncRead;
use tokio_io::codec::{Decoder, Encoder};

use tokio_timer::TimeoutError;

/// HTTP codec error.
#[derive(Debug, Clone)]
pub struct Error {
    msg: String,
}

impl ErrorTrait for Error {
    fn description(&self) -> &str {
        &self.msg
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        f.write_str(self.description())
    }
}

impl From<String> for Error {
    fn from(msg: String) -> Error {
        Error { msg: msg }
    }
}

impl<'a> From<&'a str> for Error {
    fn from(msg: &'a str) -> Error {
        Error::from(msg.to_string())
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::from(format!("IO error: {}", err))
    }
}

impl From<generic::Error> for Error {
    fn from(err: generic::Error) -> Error {
        Error::from(err.description())
    }
}

impl<T> From<TimeoutError<T>> for Error {
    fn from(err: TimeoutError<T>) -> Error {
        Error::from(format!("request timeout: {}", err))
    }
}

/// HTTP method.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Method {
    OPTIONS,
    HEAD,
    GET,
    POST,
    PUT,
    DELETE,
    TRACE,
    CONNECT,
}

impl Method {
    /// Get method name.
    fn name(self) -> &'static str {
        match self {
            Method::OPTIONS => "OPTIONS",
            Method::HEAD    => "HEAD",
            Method::GET     => "GET",
            Method::POST    => "POST",
            Method::PUT     => "PUT",
            Method::DELETE  => "DELETE",
            Method::TRACE   => "TRACE",
            Method::CONNECT => "CONNECT",
        }
    }
}

/// Valid URL schemes.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Scheme {
    HTTP,
    HTTPS,
}

impl Scheme {
    /// Get default port for this URL scheme.
    fn default_port(self) -> u16 {
        match self {
            Scheme::HTTP  => 80,
            Scheme::HTTPS => 443,
        }
    }
}

impl FromStr for Scheme {
    type Err = Error;

    fn from_str(method: &str) -> Result<Scheme, Error> {
        match &method.to_lowercase() as &str {
            "http"  => Ok(Scheme::HTTP),
            "https" => Ok(Scheme::HTTPS),
            _ => Err(Error::from("invalid URL scheme")),
        }
    }
}

/// HTTP request.
#[derive(Clone)]
pub struct Request {
    host:             String,
    port:             u16,
    inner:            GenericRequestBuilder,
    timeout:          Option<Duration>,
    max_line_length:  usize,
    max_header_lines: usize,
}

impl Request {
    /// Create a new HTTP request.
    pub fn new(method: Method, url: &str) -> Result<Request, Error> {
        let url = Url::from_str(url)
            .map_err(|_| Error::from("malformed URL"))?;

        let scheme = Scheme::from_str(url.scheme())?;

        let host = url.host();
        let port = url.port()
            .unwrap_or(scheme.default_port());

        let mut path = url.path()
            .to_string();

        if let Some(query) = url.query() {
            path += query;
        }

        let inner = GenericRequestBuilder::new(
            "HTTP",
            "1.0",
            method.name(),
            &path);

        let builder = Request {
            host:             host.to_string(),
            port:             port,
            inner:            inner,
            timeout:          Some(Duration::from_secs(20)),
            max_line_length:  4096,
            max_header_lines: 1024,
        };

        Ok(builder)
    }

    /// Create a new GET request.
    pub fn get(url: &str) -> Result<Request, Error> {
        Request::new(Method::GET, url)
    }

    /// Set protocol version.
    pub fn set_version(mut self, version: &str) -> Request {
        self.inner = self.inner.set_version(version);
        self
    }

    /// Add a given header field.
    pub fn add_header_field(mut self, field: HeaderField) -> Request {
        self.inner = self.inner.add_header_field(field);
        self
    }

    /// Set request timeout.
    pub fn set_request_timeout(mut self, timeout: Option<Duration>) -> Request {
        self.timeout = timeout;
        self
    }

    /// Set maximum length of a single line accepted by the response parser.
    pub fn set_max_line_length(mut self, max_length: usize) -> Request {
        self.max_line_length = max_length;
        self
    }

    /// Set maximum number of header lines accepted by the response parser.
    pub fn set_max_header_lines(mut self, max_lines: usize) -> Request {
        self.max_header_lines = max_lines;
        self
    }

    /// Send the request and return a future response
    pub fn send(self, handle: &TokioHandle) -> Result<FutureResponse, Error> {
        // TODO: add TLS layer in case of HTTPS scheme

        let addr = net::utils::get_socket_address((self.host.as_ref(), self.port))
            .map_err(|_| Error::from("unable to resolve a given socket address"))?;

        let timeout = self.timeout.clone();

        // single request-response cycle
        let response = TcpStream::connect(&addr, &handle)
            .map_err(|err| Error::from(err))
            .and_then(move |stream| {
                stream.framed(ClientCodec::new(self.max_line_length, self.max_header_lines))
                    .send(self.inner.build())
                    .map_err(|err| Error::from(err))
                    .and_then(|stream| {
                        stream.into_future()
                            .map_err(|(err, _)| err)
                            .and_then(|(response, _)| {
                                response.ok_or(Error::from("server closed connection unexpectedly"))
                            })
                    })
            });

        if let Some(timeout) = timeout {
            let response = DEFAULT_TIMER
                .timeout(response, timeout);

            Ok(FutureResponse::new(response))
        } else {
            Ok(FutureResponse::new(response))
        }
    }
}

/// HTTP response.
pub struct Response {
    inner: GenericResponse,
}

impl Response {
    /// Create a new HTTP response from a given generic response.
    fn new(response: GenericResponse) -> Result<Response, Error> {
        {
            let header = response.header();
            let protocol = header.protocol();
            let version = header.version();

            if protocol != "HTTP" {
                return Err(Error::from("invalid protocol"));
            }

            if version != "1.0" && version != "1.1" {
                return Err(Error::from("unsupported HTTP version"));
            }
        }

        let response = Response {
            inner: response,
        };

        Ok(response)
    }

    /// Get protocol version.
    pub fn version(&self) -> &str {
        self.inner.header()
            .version()
    }

    /// Get status code.
    pub fn status_code(&self) -> u16 {
        self.inner.header()
            .status_code()
    }

    /// Get status line.
    pub fn status_line(&self) -> &str {
        self.inner.header()
            .status_line()
    }

    /// Get response body.
    pub fn body(&self) -> &[u8] {
        self.inner.body()
    }

    /// Get header fields corresponding to a given name.
    pub fn get_header_fields(&self, name: &str) -> &[HeaderField] {
        self.inner.header()
            .get_header_fields(name)
    }

    /// Get last header field of a given name.
    pub fn get_header_field(&self, name: &str) -> Option<&HeaderField> {
        self.inner.header()
            .get_header_field(name)
    }
}

/// Future response. This struct implements the Futere trait yielding Response.
pub struct FutureResponse {
    inner: Box<Future<Item=Response, Error=Error>>,
}

impl FutureResponse {
    /// Create a new future response.
    fn new<F>(future: F) -> FutureResponse
        where F: 'static + Future<Item=Response, Error=Error> {
        FutureResponse {
            inner: Box::new(future),
        }
    }
}

impl Future for FutureResponse {
    type Item = Response;
    type Error = Error;

    fn poll(&mut self) -> Poll<Response, Error> {
        self.inner.poll()
    }
}

/// HTTP client codec.
struct ClientCodec {
    inner: GenericClientCodec,
}

impl ClientCodec {
    /// Create a new codec instance.
    fn new(max_line_length: usize, max_header_lines: usize) -> ClientCodec {
        ClientCodec {
            inner: GenericClientCodec::new(max_line_length, max_header_lines),
        }
    }
}

impl Decoder for ClientCodec {
    type Item = Response;
    type Error = Error;

    fn decode(&mut self, data: &mut BytesMut) -> Result<Option<Response>, Error> {
        if let Some(response) = self.inner.decode(data)? {
            // try to parse a given generic response
            let response = Response::new(response)?;

            Ok(Some(response))
        } else {
            Ok(None)
        }
    }
}

impl Encoder for ClientCodec {
    type Item = GenericRequest;
    type Error = io::Error;

    fn encode(&mut self, message: GenericRequest, buffer: &mut BytesMut) -> Result<(), io::Error> {
        self.inner.encode(message, buffer)
    }
}
<commit_msg>Remove HTTPS scheme from the asynchronous HTTP protocol implementation<commit_after>// Copyright 2017 click2stream, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

pub mod generic;

use std::io;
use std::fmt;

use std::error::Error as ErrorTrait;
use std::fmt::{Display, Formatter};
use std::str::FromStr;
use std::time::Duration;

use net;

use net::url::Url;

use timer::DEFAULT_TIMER;

use self::generic::HeaderField;
use self::generic::ClientCodec as GenericClientCodec;
use self::generic::Request as GenericRequest;
use self::generic::Response as GenericResponse;
use self::generic::RequestBuilder as GenericRequestBuilder;

use bytes::BytesMut;

use futures::{Future, Poll, Sink, Stream};

use tokio_core::net::TcpStream;
use tokio_core::reactor::Handle as TokioHandle;

use tokio_io::AsyncRead;
use tokio_io::codec::{Decoder, Encoder};

use tokio_timer::TimeoutError;

/// HTTP codec error.
#[derive(Debug, Clone)]
pub struct Error {
    msg: String,
}

impl ErrorTrait for Error {
    fn description(&self) -> &str {
        &self.msg
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        f.write_str(self.description())
    }
}

impl From<String> for Error {
    fn from(msg: String) -> Error {
        Error { msg: msg }
    }
}

impl<'a> From<&'a str> for Error {
    fn from(msg: &'a str) -> Error {
        Error::from(msg.to_string())
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::from(format!("IO error: {}", err))
    }
}

impl From<generic::Error> for Error {
    fn from(err: generic::Error) -> Error {
        Error::from(err.description())
    }
}

impl<T> From<TimeoutError<T>> for Error {
    fn from(err: TimeoutError<T>) -> Error {
        Error::from(format!("request timeout: {}", err))
    }
}

/// HTTP method.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Method {
    OPTIONS,
    HEAD,
    GET,
    POST,
    PUT,
    DELETE,
    TRACE,
    CONNECT,
}

impl Method {
    /// Get method name.
    fn name(self) -> &'static str {
        match self {
            Method::OPTIONS => "OPTIONS",
            Method::HEAD    => "HEAD",
            Method::GET     => "GET",
            Method::POST    => "POST",
            Method::PUT     => "PUT",
            Method::DELETE  => "DELETE",
            Method::TRACE   => "TRACE",
            Method::CONNECT => "CONNECT",
        }
    }
}

/// Valid URL schemes.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Scheme {
    HTTP,
}

impl Scheme {
    /// Get default port for this URL scheme.
    fn default_port(self) -> u16 {
        match self {
            Scheme::HTTP  => 80,
        }
    }
}

impl FromStr for Scheme {
    type Err = Error;

    fn from_str(method: &str) -> Result<Scheme, Error> {
        match &method.to_lowercase() as &str {
            "http"  => Ok(Scheme::HTTP),
            _ => Err(Error::from("invalid URL scheme")),
        }
    }
}

/// HTTP request.
#[derive(Clone)]
pub struct Request {
    host:             String,
    port:             u16,
    inner:            GenericRequestBuilder,
    timeout:          Option<Duration>,
    max_line_length:  usize,
    max_header_lines: usize,
}

impl Request {
    /// Create a new HTTP request.
    pub fn new(method: Method, url: &str) -> Result<Request, Error> {
        let url = Url::from_str(url)
            .map_err(|_| Error::from("malformed URL"))?;

        let scheme = Scheme::from_str(url.scheme())?;

        let host = url.host();
        let port = url.port()
            .unwrap_or(scheme.default_port());

        let mut path = url.path()
            .to_string();

        if let Some(query) = url.query() {
            path += query;
        }

        let inner = GenericRequestBuilder::new(
            "HTTP",
            "1.0",
            method.name(),
            &path);

        let builder = Request {
            host:             host.to_string(),
            port:             port,
            inner:            inner,
            timeout:          Some(Duration::from_secs(20)),
            max_line_length:  4096,
            max_header_lines: 1024,
        };

        Ok(builder)
    }

    /// Create a new GET request.
    pub fn get(url: &str) -> Result<Request, Error> {
        Request::new(Method::GET, url)
    }

    /// Set protocol version.
    pub fn set_version(mut self, version: &str) -> Request {
        self.inner = self.inner.set_version(version);
        self
    }

    /// Add a given header field.
    pub fn add_header_field(mut self, field: HeaderField) -> Request {
        self.inner = self.inner.add_header_field(field);
        self
    }

    /// Set request timeout.
    pub fn set_request_timeout(mut self, timeout: Option<Duration>) -> Request {
        self.timeout = timeout;
        self
    }

    /// Set maximum length of a single line accepted by the response parser.
    pub fn set_max_line_length(mut self, max_length: usize) -> Request {
        self.max_line_length = max_length;
        self
    }

    /// Set maximum number of header lines accepted by the response parser.
    pub fn set_max_header_lines(mut self, max_lines: usize) -> Request {
        self.max_header_lines = max_lines;
        self
    }

    /// Send the request and return a future response
    pub fn send(self, handle: &TokioHandle) -> Result<FutureResponse, Error> {
        let addr = net::utils::get_socket_address((self.host.as_ref(), self.port))
            .map_err(|_| Error::from("unable to resolve a given socket address"))?;

        let timeout = self.timeout.clone();

        // single request-response cycle
        let response = TcpStream::connect(&addr, &handle)
            .map_err(|err| Error::from(err))
            .and_then(move |stream| {
                stream.framed(ClientCodec::new(self.max_line_length, self.max_header_lines))
                    .send(self.inner.build())
                    .map_err(|err| Error::from(err))
                    .and_then(|stream| {
                        stream.into_future()
                            .map_err(|(err, _)| err)
                            .and_then(|(response, _)| {
                                response.ok_or(Error::from("server closed connection unexpectedly"))
                            })
                    })
            });

        if let Some(timeout) = timeout {
            let response = DEFAULT_TIMER
                .timeout(response, timeout);

            Ok(FutureResponse::new(response))
        } else {
            Ok(FutureResponse::new(response))
        }
    }
}

/// HTTP response.
pub struct Response {
    inner: GenericResponse,
}

impl Response {
    /// Create a new HTTP response from a given generic response.
    fn new(response: GenericResponse) -> Result<Response, Error> {
        {
            let header = response.header();
            let protocol = header.protocol();
            let version = header.version();

            if protocol != "HTTP" {
                return Err(Error::from("invalid protocol"));
            }

            if version != "1.0" && version != "1.1" {
                return Err(Error::from("unsupported HTTP version"));
            }
        }

        let response = Response {
            inner: response,
        };

        Ok(response)
    }

    /// Get protocol version.
    pub fn version(&self) -> &str {
        self.inner.header()
            .version()
    }

    /// Get status code.
    pub fn status_code(&self) -> u16 {
        self.inner.header()
            .status_code()
    }

    /// Get status line.
    pub fn status_line(&self) -> &str {
        self.inner.header()
            .status_line()
    }

    /// Get response body.
    pub fn body(&self) -> &[u8] {
        self.inner.body()
    }

    /// Get header fields corresponding to a given name.
    pub fn get_header_fields(&self, name: &str) -> &[HeaderField] {
        self.inner.header()
            .get_header_fields(name)
    }

    /// Get last header field of a given name.
    pub fn get_header_field(&self, name: &str) -> Option<&HeaderField> {
        self.inner.header()
            .get_header_field(name)
    }
}

/// Future response. This struct implements the Futere trait yielding Response.
pub struct FutureResponse {
    inner: Box<Future<Item=Response, Error=Error>>,
}

impl FutureResponse {
    /// Create a new future response.
    fn new<F>(future: F) -> FutureResponse
        where F: 'static + Future<Item=Response, Error=Error> {
        FutureResponse {
            inner: Box::new(future),
        }
    }
}

impl Future for FutureResponse {
    type Item = Response;
    type Error = Error;

    fn poll(&mut self) -> Poll<Response, Error> {
        self.inner.poll()
    }
}

/// HTTP client codec.
struct ClientCodec {
    inner: GenericClientCodec,
}

impl ClientCodec {
    /// Create a new codec instance.
    fn new(max_line_length: usize, max_header_lines: usize) -> ClientCodec {
        ClientCodec {
            inner: GenericClientCodec::new(max_line_length, max_header_lines),
        }
    }
}

impl Decoder for ClientCodec {
    type Item = Response;
    type Error = Error;

    fn decode(&mut self, data: &mut BytesMut) -> Result<Option<Response>, Error> {
        if let Some(response) = self.inner.decode(data)? {
            // try to parse a given generic response
            let response = Response::new(response)?;

            Ok(Some(response))
        } else {
            Ok(None)
        }
    }
}

impl Encoder for ClientCodec {
    type Item = GenericRequest;
    type Error = io::Error;

    fn encode(&mut self, message: GenericRequest, buffer: &mut BytesMut) -> Result<(), io::Error> {
        self.inner.encode(message, buffer)
    }
}
<|endoftext|>


<commit_before>use orbtk::{
    prelude::*,
    // only instantiate the `default` theme
    widgets::themes::theme_orbtk::{
        register_default_fonts, THEME_DEFAULT, THEME_DEFAULT_COLORS_DARK, THEME_DEFAULT_FONTS,
    },
};

// German localization file.
static POPUP_DE_DE: &str = include_str!("assets/popup/popup_de_DE.ron");

static DARK_EXT: &str = include_str!("assets/popup/default_dark.ron");

static ID_BUTTON: &str = "Toggle Popup";
static ID_GRID: &str = "PopupGrid";
static ID_GRID_PLACEMENT: &str = "Selection GRID";
static ID_MAIN_VIEW: &str = "MainView";
static ID_POPUP: &str = "Popup";
static ID_POPUP_STACK: &str = "PopupStack";
static ID_PLACEMENT_COMBO_BOX: &str = "Placement Selecton Box";
static ID_PLACEMENT_OFFSET: &str = "Placement Offset";
static ID_PLACEMENT_OFFSET_LABEL: &str = "Offset";
static ID_PLACEMENT_COMBO_BOX_LABEL: &str = "Placement Label";
static ID_TARGET: &str = "Target";

/// Valid `actions` that are handled as state changes in the `MainView` widget.
#[derive(Copy, Clone)]
enum MainViewAction {
    /// Toggle the visibility of the popup
    TogglePopup,

    /// Update the offset of the popup relative to the target
    UpdateOffset,

    /// Update the placement of the popup relative to the target
    UpdatePlacement,
}

/// Valid `structures` that are handled inside the state of the `MainView` widget.
#[derive(AsAny, Default)]
struct MainViewState {
    _action: Option<MainViewAction>,
}

/// Method definitions, that react on any given state change inside the `MainView` widget.
impl MainViewState {
    fn _action(&mut self, action: impl Into<Option<MainViewAction>>) {
        self._action = action.into();
    }

    fn toggle_popup(&mut self, ctx: &mut Context<'_>) {
        let open = ctx.child(ID_POPUP).clone::<bool>("open");

        if open {
            Popup::open_set(&mut ctx.child(ID_POPUP), false);
            Popup::visibility_set(&mut ctx.child(ID_POPUP), Visibility::Collapsed);
            Button::text_set(&mut ctx.child(ID_BUTTON), "Click me to show the popup");
        } else {
            Popup::visibility_set(&mut ctx.child(ID_POPUP), Visibility::Visible);
            Popup::open_set(&mut ctx.child(ID_POPUP), true);
            Button::text_set(&mut ctx.child(ID_BUTTON), "Click me to hide the popup");
        }
    }

    fn update_placement(&mut self, ctx: &mut Context<'_>) {
        let selected_index: i32 = ctx.child(ID_PLACEMENT_COMBO_BOX).clone("selected_index");
        let placement: Placement = ctx.child(ID_POPUP).clone_or_default("placement");
        match selected_index {
            0 => Popup::placement_set(&mut ctx.child(ID_POPUP), placement.bottom()),
            1 => Popup::placement_set(&mut ctx.child(ID_POPUP), placement.bottom_left()),
            2 => Popup::placement_set(&mut ctx.child(ID_POPUP), placement.bottom_right()),
            3 => Popup::placement_set(&mut ctx.child(ID_POPUP), placement.left()),
            4 => Popup::placement_set(&mut ctx.child(ID_POPUP), placement.right()),
            5 => Popup::placement_set(&mut ctx.child(ID_POPUP), placement.top()),
            6 => Popup::placement_set(&mut ctx.child(ID_POPUP), placement.top_left()),
            7 => Popup::placement_set(&mut ctx.child(ID_POPUP), placement.top_right()),
            _ => panic!(),
        }
        if cfg!(debug) {
            println!(
                "popup_v2: Placement {:?} (index: {:?}).",
                ctx.child(ID_POPUP).get::<Placement>("placement"),
                selected_index
            );
        }
    }

    fn update_offset(&mut self, ctx: &mut Context<'_>) {
        let offset: f64 = ctx.child(ID_PLACEMENT_OFFSET).clone("val");
        Popup::offset_set(&mut ctx.child(ID_POPUP), offset);

        if cfg!(debug) {
            println!(
                "popup_v2: Offset {:?}.",
                ctx.child(ID_POPUP).get::<f64>("offset")
            );
        }
    }
}

/// Associated methods handled inside the `MainViewState`
impl State for MainViewState {
    fn init(&mut self, _registry: &mut Registry, ctx: &mut Context) {
        // initialize the popup properties
        ctx.child(ID_POPUP).set("open", false);
        ctx.child(ID_POPUP).set("visibility", Visibility::Collapsed);
    }

    fn messages(
        &mut self,
        mut messages: MessageReader,
        _registry: &mut Registry,
        ctx: &mut Context,
    ) {
        for message in messages.read::<MainViewAction>() {
            match message {
                MainViewAction::TogglePopup => {
                    MainViewState::toggle_popup(self, ctx);
                }
                MainViewAction::UpdatePlacement => {
                    MainViewState::update_placement(self, ctx);
                    }
                MainViewAction::UpdateOffset => {
                    MainViewState::update_offset(self, ctx);
                }
            }
        }
    }
}

fn theme() -> Theme {
    register_default_fonts(Theme::from_config(
        ThemeConfig::from(DARK_EXT)
            .extend(ThemeConfig::from(THEME_DEFAULT))
            .extend(ThemeConfig::from(THEME_DEFAULT_COLORS_DARK))
            .extend(ThemeConfig::from(THEME_DEFAULT_FONTS)),
    ))
}

// Used to define ComboBox list members
type List = Vec<String>;

// constructs the MainView
widget!(
    MainView<MainViewState> {
    /// Active seleced index of combo box.
    selected_index: i32,

    /// Acitve selected position of popup.
    placements: List
    }
);

/// The template implementation of the main view
/// GUI elements are styled using the "style" attribute referencing to a ron based css
impl Template for MainView {
    fn template(self, id: Entity, ctx: &mut BuildContext) -> Self {
        let placements = vec![
            // TODO: make it sort independent
            "Bottom".to_string(),
            "BottomLeft".to_string(),
            "BottomRight".to_string(),
            "Left".to_string(),
            "Right".to_string(),
            "Top".to_string(),
            "TopLeft".to_string(),
            "TopRight".to_string(),
        ];
        let count_placements = placements.len();

        let target_container = Container::new()
            .id(ID_TARGET)
            .attach(Grid::row(2))
            .attach(Grid::column(1))
            .style("container_form")
            .child(
                Stack::new()
                    .orientation("vertical")
                    .spacing(16.0)
                    .child(
                        TextBlock::new()
                            .style("target_text_block")
                            .text("Target")
                            .build(ctx),
                    )
                    .child(
                        TextBlock::new()
                            .style("target_text_block")
                            .text("Target content")
                            .build(ctx),
                    )
                    .build(ctx),
            )
            .build(ctx);

        let popup = Popup::new()
            .id(ID_POPUP)
            .name(ID_POPUP)
            .style("popup_form")
            // alternative: popup is target of given coordinates (Point)
            //.target(Point::new(0.0, 0.0))
            .height(180.0)
            .open(false)
            .offset(1.0)
            .width(180.0)
            .target(target_container)
        .child(
            Container::new()
                    .child(
                        Stack::new()
                            .id(ID_POPUP_STACK)
                            .orientation("vertical")
                            .spacing(16.0)
                .child(
                    TextBlock::new()
                                    .style("popup_text_block")
                        .h_align("center")
                                    .v_align("center")
                                    .text("Popup Header")
                                    .build(ctx),
                )
                            .child(
                                TextBlock::new()
                                    .style("popup_text_block")
                                    .h_align("center")
                                    .v_align("center")
                                    .text("Popup content")
                                    .build(ctx),
        )
                            .build(ctx),
                    )
                    .build(ctx),
            )
            .build(ctx);

        let _ = ctx.append_child_to_overlay(popup);

        // Widget:  MainView
        self.id(ID_MAIN_VIEW)
            .name(ID_MAIN_VIEW)
            .margin(20.0)
            .placements(placements) // vector with placement strings
            .child(
                Grid::new()
                    .id(ID_GRID)
                    .rows("80, 200, 200, *")
                    .columns("200, 200, 250")
                .child(
                    Button::new()
                            .id(ID_BUTTON)
                            .attach(Grid::row(0))
                            .attach(Grid::column(1))
                            .text("Click me to show the popup")
                            .on_click(move |state, _entity| -> bool {
                                state.send_message(MainViewAction::TogglePopup, id);
                            true
                        })
                            .build(ctx),
                )
                    .child(
                        Grid::new()
                            .id(ID_GRID_PLACEMENT)
                            .attach(Grid::row(0))
                            .attach(Grid::column(2))
                            .rows("auto, 4, auto")
                            .columns("120, 8, auto")
                            //.style("container_form")
                            .name(ID_GRID_PLACEMENT)
                            .child(
                                TextBlock::new()
                                    .id(ID_PLACEMENT_COMBO_BOX_LABEL)
                                    .attach(Grid::row(0))
                                    .attach(Grid::column(0))
                                    .h_align("end")
                                    .text("Placement:")
                                    .v_align("center")
                                    .build(ctx),
                            )
                            .child(
                                ComboBox::new()
                                    .id(ID_PLACEMENT_COMBO_BOX)
                                    .attach(Grid::row(0))
                                    .attach(Grid::column(2))
                                    .count(count_placements)
                                    //.style("combo_box")
                                    .items_builder(move |ibc, index| {
                                        let text = MainView::placements_ref(&ibc.get_widget(id))
                                            [index]
                                            .clone();
                                        TextBlock::new().v_align("center").text(text).build(ibc)
                                    })
                                    .on_changed("selected_index", move |states, _entity| {
                                        states.send_message(MainViewAction::UpdatePlacement, id);
                                    })
                                    .selected_index(id)
                                    .build(ctx),
                            )
                            .child(
                                TextBlock::new()
                                    .id(ID_PLACEMENT_OFFSET_LABEL)
                                    .attach(Grid::row(2))
                                    .attach(Grid::column(0))
                                    .h_align("end")
                                    .text("Offset:")
                                    .v_align("center")
                                    .build(ctx),
                            )
                            .child(
                                NumericBox::new()
                                    .id(ID_PLACEMENT_OFFSET)
                                    .attach(Grid::row(2))
                                    .attach(Grid::column(2))
                                    .style("popup_numeric_box")
                                    .max(50)
                                    .step(1)
                                    .val(5)
                                    //.water_mark("in pixel")
                                    .on_changed("val", move |states, _entity| {
                                        states.send_message(MainViewAction::UpdateOffset, id);
                                    })
                                    .build(ctx),
                            )
                            .build(ctx),
                    )
                    .child(target_container)
                    .build(ctx),
        )
    }
}

fn main() {
    // if no dictionary is set for the default language
    // the content of the text property will drawn.
    let localization = RonLocalization::create()
        .language("de_DE")
        //.language("en_US")
        .dictionary("de_DE", POPUP_DE_DE)
        .build();

    Application::new()
        .localization(localization)
        .theme(theme())
        .window(|ctx| {
            Window::new()
                .title("OrbTk - Popup example")
                .position((100.0, 100.0))
                .size(680, 690.0)
                .resizeable(true)
                .child(MainView::new().build(ctx))
                .build(ctx)
        })
        .run();
}
<commit_msg>orbtk: example popup update<commit_after>use orbtk::{
    prelude::*,
    // only instantiate the `default` theme
    widgets::themes::theme_orbtk::{
        register_default_fonts, THEME_DEFAULT, THEME_DEFAULT_COLORS_DARK, THEME_DEFAULT_FONTS,
    },
};

// German localization file.
static POPUP_DE_DE: &str = include_str!("assets/popup/popup_de_DE.ron");

static DARK_EXT: &str = include_str!("assets/popup/default_dark.ron");

static ID_BUTTON: &str = "Toggle Popup";
static ID_GRID: &str = "PopupGrid";
static ID_GRID_PLACEMENT: &str = "Selection GRID";
static ID_MAIN_VIEW: &str = "MainView";
static ID_POPUP: &str = "Popup";
static ID_POPUP_STACK: &str = "PopupStack";
static ID_PLACEMENT_COMBO_BOX: &str = "Placement Selecton Box";
static ID_PLACEMENT_OFFSET: &str = "Placement Offset";
static ID_PLACEMENT_OFFSET_LABEL: &str = "Offset";
static ID_PLACEMENT_COMBO_BOX_LABEL: &str = "Placement Label";
static ID_TARGET: &str = "Target";

/// Valid `actions` that are handled as state changes in the `MainView` widget.
#[derive(Copy, Clone)]
enum MainViewAction {
    /// Toggle the visibility of the popup
    TogglePopup,

    /// Update the offset of the popup relative to the target
    UpdateOffset,

    /// Update the placement of the popup relative to the target
    UpdatePlacement,
}

/// Valid `structures` that are handled inside the state of the `MainView` widget.
#[derive(AsAny, Default)]
struct MainViewState {
    _action: Option<MainViewAction>,
}

/// Method definitions, that react on any given state change inside the `MainView` widget.
impl MainViewState {
    fn _action(&mut self, action: impl Into<Option<MainViewAction>>) {
        self._action = action.into();
    }

    fn toggle_popup(&mut self, ctx: &mut Context<'_>) {
        let open = ctx.child(ID_POPUP).clone::<bool>("open");

        if open {
            Popup::open_set(&mut ctx.child(ID_POPUP), false);
            Popup::visibility_set(&mut ctx.child(ID_POPUP), Visibility::Collapsed);
            Button::text_set(&mut ctx.child(ID_BUTTON), "Click me to show the popup");
        } else {
            Popup::visibility_set(&mut ctx.child(ID_POPUP), Visibility::Visible);
            Popup::open_set(&mut ctx.child(ID_POPUP), true);
            Button::text_set(&mut ctx.child(ID_BUTTON), "Click me to hide the popup");
        }
    }

    fn update_placement(&mut self, ctx: &mut Context<'_>) {
        let selected_index: i32 = ctx.child(ID_PLACEMENT_COMBO_BOX).clone("selected_index");
        let placement: Placement = ctx.child(ID_POPUP).clone_or_default("placement");
        match selected_index {
            0 => Popup::placement_set(&mut ctx.child(ID_POPUP), placement.bottom()),
	    1 => Popup::placement_set(&mut ctx.child(ID_POPUP), placement.left()),
	    2 => Popup::placement_set(&mut ctx.child(ID_POPUP), placement.right()),
	    3 => Popup::placement_set(&mut ctx.child(ID_POPUP), placement.top()),
            _ => panic!(),
        }
        if cfg!(debug) {
            println!(
                "popup_v2: Placement {:?} (index: {:?}).",
                ctx.child(ID_POPUP).get::<Placement>("placement"),
                selected_index
            );
        }
    }

    fn update_offset(&mut self, ctx: &mut Context<'_>) {
        let offset: f64 = ctx.child(ID_PLACEMENT_OFFSET).clone("val");
        Popup::offset_set(&mut ctx.child(ID_POPUP), offset);

        if cfg!(debug) {
            println!(
                "popup_v2: Offset {:?}.",
                ctx.child(ID_POPUP).get::<f64>("offset")
            );
        }
    }
}

/// Associated methods handled inside the `MainViewState`
impl State for MainViewState {
    fn init(&mut self, _registry: &mut Registry, ctx: &mut Context) {
        // initialize the popup properties
	let offset: f64 = ctx.child(ID_PLACEMENT_OFFSET).clone("val");
	Popup::offset_set(&mut ctx.child(ID_POPUP), offset);
	Popup::open_set(&mut ctx.child(ID_POPUP), false);
	Popup::visibility_set(&mut ctx.child(ID_POPUP), Visibility::Collapsed);
    }

    fn messages(
        &mut self,
        mut messages: MessageReader,
        _registry: &mut Registry,
        ctx: &mut Context,
    ) {
        for message in messages.read::<MainViewAction>() {
            match message {
                MainViewAction::TogglePopup => {
                    MainViewState::toggle_popup(self, ctx);
                }
                MainViewAction::UpdatePlacement => {
                    MainViewState::update_placement(self, ctx);
                    }
                MainViewAction::UpdateOffset => {
                    MainViewState::update_offset(self, ctx);
                }
            }
        }
    }
}

fn theme() -> Theme {
    register_default_fonts(Theme::from_config(
        ThemeConfig::from(DARK_EXT)
            .extend(ThemeConfig::from(THEME_DEFAULT))
            .extend(ThemeConfig::from(THEME_DEFAULT_COLORS_DARK))
            .extend(ThemeConfig::from(THEME_DEFAULT_FONTS)),
    ))
}

// Used to define ComboBox list members
type List = Vec<String>;

// constructs the MainView
widget!(
    MainView<MainViewState> {
    /// Active seleced index of combo box.
    selected_index: i32,

    /// Acitve selected position of popup.
    placements: List
    }
);

/// The template implementation of the main view
/// GUI elements are styled using the "style" attribute referencing to a ron based css
impl Template for MainView {
    fn template(self, id: Entity, ctx: &mut BuildContext) -> Self {
        let placements = vec![
            // TODO: make it sort independent
            "Bottom".to_string(),
            "Left".to_string(),
            "Right".to_string(),
            "Top".to_string(),
        ];
        let count_placements = placements.len();

        let target_container = Container::new()
            .id(ID_TARGET)
            .attach(Grid::row(2))
            .attach(Grid::column(1))
            .style("container_form")
            .child(
                Stack::new()
                    .orientation("vertical")
                    .spacing(16.0)
                    .child(
                        TextBlock::new()
                            .style("target_text_block")
                            .text("Target")
                            .build(ctx),
                    )
                    .child(
                        TextBlock::new()
                            .style("target_text_block")
                            .text("Target content")
                            .build(ctx),
                    )
                    .build(ctx),
            )
            .build(ctx);

        let popup = Popup::new()
            .id(ID_POPUP)
            .name(ID_POPUP)
            .style("popup_form")
            // alternative: popup is target of given coordinates (Point)
            //.target(Point::new(0.0, 0.0))
            .height(180.0)
            .open(false)
            .offset(1.0)
            .width(180.0)
            .target(target_container)
        .child(
            Container::new()
                    .child(
                        Stack::new()
                            .id(ID_POPUP_STACK)
                            .orientation("vertical")
                            .spacing(16.0)
                .child(
                    TextBlock::new()
                                    .style("popup_text_block")
                        .h_align("center")
                                    .v_align("center")
                                    .text("Popup Header")
                                    .build(ctx),
                )
                            .child(
                                TextBlock::new()
                                    .style("popup_text_block")
                                    .h_align("center")
                                    .v_align("center")
                                    .text("Popup content")
                                    .build(ctx),
        )
                            .build(ctx),
                    )
                    .build(ctx),
            )
            .build(ctx);

        let _ = ctx.append_child_to_overlay(popup);

        // Widget:  MainView
        self.id(ID_MAIN_VIEW)
            .name(ID_MAIN_VIEW)
            .margin(20.0)
            .placements(placements) // vector with placement strings
            .child(
                Grid::new()
                    .id(ID_GRID)
                    .rows("80, 200, 200, *")
                    .columns("200, 200, 250")
                .child(
                    Button::new()
                            .id(ID_BUTTON)
                            .attach(Grid::row(0))
                            .attach(Grid::column(1))
                            .text("Click me to show the popup")
                            .on_click(move |state, _entity| -> bool {
                                state.send_message(MainViewAction::TogglePopup, id);
                            true
                        })
                            .build(ctx),
                )
                    .child(
                        Grid::new()
                            .id(ID_GRID_PLACEMENT)
                            .attach(Grid::row(0))
                            .attach(Grid::column(2))
                            .rows("auto, 4, auto")
                            .columns("120, 8, auto")
                            //.style("container_form")
                            .name(ID_GRID_PLACEMENT)
                            .child(
                                TextBlock::new()
                                    .id(ID_PLACEMENT_COMBO_BOX_LABEL)
                                    .attach(Grid::row(0))
                                    .attach(Grid::column(0))
                                    .h_align("end")
                                    .text("Placement:")
                                    .v_align("center")
                                    .build(ctx),
                            )
                            .child(
                                ComboBox::new()
                                    .id(ID_PLACEMENT_COMBO_BOX)
                                    .attach(Grid::row(0))
                                    .attach(Grid::column(2))
                                    .count(count_placements)
				    .style("combo_box")
                                    .items_builder(move |ibc, index| {
                                        let text = MainView::placements_ref(&ibc.get_widget(id))
                                            [index]
                                            .clone();
                                        TextBlock::new().v_align("center").text(text).build(ibc)
                                    })
                                    .on_changed("selected_index", move |states, _entity| {
                                        states.send_message(MainViewAction::UpdatePlacement, id);
                                    })
                                    .selected_index(id)
                                    .build(ctx),
                            )
                            .child(
                                TextBlock::new()
                                    .id(ID_PLACEMENT_OFFSET_LABEL)
                                    .attach(Grid::row(2))
                                    .attach(Grid::column(0))
                                    .h_align("end")
                                    .text("Offset:")
                                    .v_align("center")
                                    .build(ctx),
                            )
                            .child(
                                NumericBox::new()
                                    .id(ID_PLACEMENT_OFFSET)
                                    .attach(Grid::row(2))
                                    .attach(Grid::column(2))
                                    .style("popup_numeric_box")
                                    .max(50)
                                    .step(1)
                                    .val(5)
                                    //.water_mark("in pixel")
                                    .on_changed("val", move |states, _entity| {
                                        states.send_message(MainViewAction::UpdateOffset, id);
                                    })
                                    .build(ctx),
                            )
                            .build(ctx),
                    )
                    .child(target_container)
                    .build(ctx),
        )
    }
}

fn main() {
    // if no dictionary is set for the default language
    // the content of the text property will drawn.
    let localization = RonLocalization::create()
        .language("de_DE")
        //.language("en_US")
        .dictionary("de_DE", POPUP_DE_DE)
        .build();

    Application::new()
        .localization(localization)
        .theme(theme())
        .window(|ctx| {
            Window::new()
                .title("OrbTk - Popup example")
                .position((100.0, 100.0))
                .size(680, 690.0)
                .resizeable(true)
                .child(MainView::new().build(ctx))
                .build(ctx)
        })
        .run();
}
<|endoftext|>


<commit_before>import stackwalk::Word;
import libc::size_t;

extern mod rustrt {
    fn rust_annihilate_box(ptr: *Word);

    #[rust_stack]
    fn rust_gc_metadata() -> *Word;

    #[rust_stack]
    fn rust_call_tydesc_glue(root: *Word, tydesc: *Word, field: size_t);
}

type SafePoint = { sp_meta: *Word, fn_meta: *Word };

unsafe fn is_safe_point(pc: *Word) -> Option<SafePoint> {
    let module_meta = rustrt::rust_gc_metadata();
    let num_safe_points_ptr: *u32 = unsafe::reinterpret_cast(&module_meta);
    let num_safe_points = *num_safe_points_ptr as Word;
    let safe_points: *Word =
        ptr::offset(unsafe::reinterpret_cast(&module_meta), 1);

    if ptr::is_null(pc) {
        return None;
    }

    let mut sp = 0 as Word;
    while sp < num_safe_points {
        let sp_loc = *ptr::offset(safe_points, sp*3) as *Word;
        if sp_loc == pc {
            return Some(
                {sp_meta: *ptr::offset(safe_points, sp*3 + 1) as *Word,
                 fn_meta: *ptr::offset(safe_points, sp*3 + 2) as *Word});
        }
        sp += 1;
    }
    return None;
}

type Visitor = fn(root: **Word, tydesc: *Word);

unsafe fn walk_safe_point(fp: *Word, sp: SafePoint, visitor: Visitor) {
    let fp_bytes: *u8 = unsafe::reinterpret_cast(&fp);
    let sp_meta_u32s: *u32 = unsafe::reinterpret_cast(&sp.sp_meta);

    let num_stack_roots = *sp_meta_u32s as uint;
    let num_reg_roots = *ptr::offset(sp_meta_u32s, 1) as uint;

    let stack_roots: *u32 =
        unsafe::reinterpret_cast(&ptr::offset(sp_meta_u32s, 2));
    let reg_roots: *u8 =
        unsafe::reinterpret_cast(&ptr::offset(stack_roots, num_stack_roots));
    let addrspaces: *Word =
        unsafe::reinterpret_cast(&ptr::offset(reg_roots, num_reg_roots));
    let tydescs: ***Word =
        unsafe::reinterpret_cast(&ptr::offset(addrspaces, num_stack_roots));

    // Stack roots
    let mut sri = 0;
    while sri < num_stack_roots {
        if *ptr::offset(addrspaces, sri) >= 1 {
            let root =
                ptr::offset(fp_bytes, *ptr::offset(stack_roots, sri) as Word)
                as **Word;
            let tydescpp = ptr::offset(tydescs, sri);
            let tydesc = if ptr::is_not_null(tydescpp) &&
                ptr::is_not_null(*tydescpp) {
                **tydescpp
            } else {
                ptr::null()
            };
            visitor(root, tydesc);
        }
        sri += 1;
    }

    // Register roots
    let mut rri = 0;
    while rri < num_reg_roots {
        if *ptr::offset(addrspaces, num_stack_roots + rri) == 1 {
            // FIXME(#2997): Need to find callee saved registers on the stack.
        }
        rri += 1;
    }
}

type Memory = uint;

const task_local_heap: Memory = 1;
const exchange_heap:   Memory = 2;
const stack:           Memory = 4;

const need_cleanup:    Memory = exchange_heap | stack;

unsafe fn walk_gc_roots(mem: Memory, visitor: Visitor) {
    let mut last_ret: *Word = ptr::null();
    do stackwalk::walk_stack |frame| {
        unsafe {
            if ptr::is_not_null(last_ret) {
                let sp = is_safe_point(last_ret);
                match sp {
                  Some(sp_info) => {
                    do walk_safe_point(frame.fp, sp_info) |root, tydesc| {
                        if ptr::is_null(tydesc) {
                            // Root is a generic box.
                            let refcount = **root;
                            if mem | task_local_heap != 0 && refcount != -1 {
                                visitor(root, tydesc);
                            } else if mem | exchange_heap != 0 {
                                visitor(root, tydesc);
                            }
                        } else {
                            // Root is a non-immediate.
                            if mem | stack != 0 {
                                visitor(root, tydesc);
                            }
                        }
                    }
                  }
                  None => ()
                }
            }
            last_ret = *ptr::offset(frame.fp, 1) as *Word;
        }
        true
    }
}

fn gc() {
    unsafe {
        let mut i = 0;
        do walk_gc_roots(task_local_heap) |_root, _tydesc| {
            // FIXME(#2997): Walk roots and mark them.
            io::stdout().write([46]); // .
            i += 1;
        }
    }
}

// This should only be called from fail, as it will drop the roots
// which are *live* on the stack, rather than dropping those that are
// dead.
fn cleanup_stack_for_failure() {
    unsafe {
        let mut i = 0;
        do walk_gc_roots(need_cleanup) |root, tydesc| {
            if ptr::is_null(tydesc) {
                rustrt::rust_annihilate_box(*root);
            } else {
                rustrt::rust_call_tydesc_glue(*root, tydesc, 3 as size_t);
            }
            i += 1;
        }
    }
}
<commit_msg>gc: Avoid double free when pointer appears on stack multiple times.<commit_after>import stackwalk::Word;
import libc::size_t;
import send_map::linear::LinearMap;

extern mod rustrt {
    fn rust_annihilate_box(ptr: *Word);

    #[rust_stack]
    fn rust_gc_metadata() -> *Word;

    #[rust_stack]
    fn rust_call_tydesc_glue(root: *Word, tydesc: *Word, field: size_t);
}

type SafePoint = { sp_meta: *Word, fn_meta: *Word };

unsafe fn is_safe_point(pc: *Word) -> Option<SafePoint> {
    let module_meta = rustrt::rust_gc_metadata();
    let num_safe_points_ptr: *u32 = unsafe::reinterpret_cast(&module_meta);
    let num_safe_points = *num_safe_points_ptr as Word;
    let safe_points: *Word =
        ptr::offset(unsafe::reinterpret_cast(&module_meta), 1);

    if ptr::is_null(pc) {
        return None;
    }

    let mut sp = 0 as Word;
    while sp < num_safe_points {
        let sp_loc = *ptr::offset(safe_points, sp*3) as *Word;
        if sp_loc == pc {
            return Some(
                {sp_meta: *ptr::offset(safe_points, sp*3 + 1) as *Word,
                 fn_meta: *ptr::offset(safe_points, sp*3 + 2) as *Word});
        }
        sp += 1;
    }
    return None;
}

type Visitor = fn(root: **Word, tydesc: *Word) -> bool;

unsafe fn walk_safe_point(fp: *Word, sp: SafePoint, visitor: Visitor) {
    let fp_bytes: *u8 = unsafe::reinterpret_cast(&fp);
    let sp_meta_u32s: *u32 = unsafe::reinterpret_cast(&sp.sp_meta);

    let num_stack_roots = *sp_meta_u32s as uint;
    let num_reg_roots = *ptr::offset(sp_meta_u32s, 1) as uint;

    let stack_roots: *u32 =
        unsafe::reinterpret_cast(&ptr::offset(sp_meta_u32s, 2));
    let reg_roots: *u8 =
        unsafe::reinterpret_cast(&ptr::offset(stack_roots, num_stack_roots));
    let addrspaces: *Word =
        unsafe::reinterpret_cast(&ptr::offset(reg_roots, num_reg_roots));
    let tydescs: ***Word =
        unsafe::reinterpret_cast(&ptr::offset(addrspaces, num_stack_roots));

    // Stack roots
    let mut sri = 0;
    while sri < num_stack_roots {
        if *ptr::offset(addrspaces, sri) >= 1 {
            let root =
                ptr::offset(fp_bytes, *ptr::offset(stack_roots, sri) as Word)
                as **Word;
            let tydescpp = ptr::offset(tydescs, sri);
            let tydesc = if ptr::is_not_null(tydescpp) &&
                ptr::is_not_null(*tydescpp) {
                **tydescpp
            } else {
                ptr::null()
            };
            if !visitor(root, tydesc) { return; }
        }
        sri += 1;
    }

    // Register roots
    let mut rri = 0;
    while rri < num_reg_roots {
        if *ptr::offset(addrspaces, num_stack_roots + rri) == 1 {
            // FIXME(#2997): Need to find callee saved registers on the stack.
        }
        rri += 1;
    }
}

type Memory = uint;

const task_local_heap: Memory = 1;
const exchange_heap:   Memory = 2;
const stack:           Memory = 4;

const need_cleanup:    Memory = exchange_heap | stack;

unsafe fn walk_gc_roots(mem: Memory, visitor: Visitor) {
    let mut last_ret: *Word = ptr::null();
    for stackwalk::walk_stack |frame| {
        unsafe {
            if ptr::is_not_null(last_ret) {
                let sp = is_safe_point(last_ret);
                match sp {
                  Some(sp_info) => {
                    for walk_safe_point(frame.fp, sp_info) |root, tydesc| {
                        if ptr::is_null(tydesc) {
                            // Root is a generic box.
                            let refcount = **root;
                            if mem | task_local_heap != 0 && refcount != -1 {
                                if !visitor(root, tydesc) { return; }
                            } else if mem | exchange_heap != 0 {
                                if !visitor(root, tydesc) { return; }
                            }
                        } else {
                            // Root is a non-immediate.
                            if mem | stack != 0 {
                                if !visitor(root, tydesc) { return; }
                            }
                        }
                    }
                  }
                  None => ()
                }
            }
            last_ret = *ptr::offset(frame.fp, 1) as *Word;
        }
    }
}

fn gc() {
    unsafe {
        for walk_gc_roots(task_local_heap) |_root, _tydesc| {
            // FIXME(#2997): Walk roots and mark them.
            io::stdout().write([46]); // .
        }
    }
}

type RootSet = LinearMap<*Word,()>;

fn RootSet() -> RootSet {
    LinearMap()
}

// This should only be called from fail, as it will drop the roots
// which are *live* on the stack, rather than dropping those that are
// dead.
fn cleanup_stack_for_failure() {
    unsafe {
        let mut roots = ~RootSet();
        for walk_gc_roots(need_cleanup) |root, tydesc| {
            // Track roots to avoid double frees.
            if option::is_some(roots.find(&*root)) {
                again;
            }
            roots.insert(*root, ());

            if ptr::is_null(tydesc) {
                rustrt::rust_annihilate_box(*root);
            } else {
                rustrt::rust_call_tydesc_glue(*root, tydesc, 3 as size_t);
            }
        }
    }
}
<|endoftext|>


<commit_before>mod command;

use std::io::{stdin, stdout};
use std::io::prelude::*;
use std::borrow::Cow;

use cpu::cpu::Cpu;
use cpu::cpu::GFX_HEIGHT;
use cpu::cpu::GFX_WIDTH;
use self::command::Command;

pub struct Debugger {
    cpu: Cpu,
    last_commad: Option<Command>,
}

impl Debugger {
    pub fn new(cpu: Cpu) -> Debugger {
        Debugger {
            cpu: cpu,
            last_commad: None,
        }
    }

    pub fn run(&mut self) {
        loop {
            print!("chip8> ");
            stdout().flush().unwrap();

            let command = match (read_stdin().parse(), self.last_commad) {
                (Ok(Command::Repeat), Some(c)) => Ok(c),
                (Ok(Command::Repeat), None) => Err("No last command".into()),
                (Ok(c), _) => Ok(c),
                (Err(e), _) => Err(e),
            };

            match command {
                Ok(Command::Step(count)) => self.step(count),
                Ok(Command::Exit) => break,
                Ok(Command::Repeat) => unreachable!(),
                Err(ref e) => println!("{}", e),
            }

            self.last_commad = command.ok();
        }
    }

    pub fn step(&mut self, count: usize) {
        for _ in 0..count {
            let curr_pc = self.cpu.curr_pc();
            let curr_index = self.cpu.curr_index();
            let curr_opcode = self.cpu.curr_opcode();
            let curr_regs = self.cpu.curr_regs();
            let curr_stack = self.cpu.curr_stack();
            let curr_sp = self.cpu.curr_sp();
            let curr_gfx = self.cpu.curr_gfx();

            print!("pc:{:04X},", curr_pc);
            print!("index:{:04X},", curr_index);
            println!("opcode:{:04X}", curr_opcode);
            println!("=============================================");

            println!("stack:");
            print_stack(curr_stack, curr_sp);
            println!("=============================================");
            println!("registers:");
            print_regs(curr_regs);
            println!("=============================================");
            println!("screen:");
            print_gfx(curr_gfx);
            println!("=============================================");

            self.cpu.emulate_cycle();
        }
    }
}

fn print_gfx(gfx: Vec<u8>) {
    for i in 0..GFX_HEIGHT {
        for j in 0..GFX_WIDTH {
            print!("{}", gfx[(i * GFX_WIDTH + j) as usize]);
        }
        println!();
    }
}

fn print_regs(regs: Vec<u8>) {
    println!("| 0| 1| 2| 3| 4| 5| 6| 7| 8| 9| A| B| C| D| E| F|");
    for i in 0..regs.len() {
        print!("|{:02X}", regs[i as usize]);
    }
    println!("|");
}

fn print_stack(stack: Vec<usize>, sp: usize) {
    for i in 0..stack.len() {
        if i == sp {
            print!("[");
        }
        print!("{:04X}", stack[i as usize]);
        if i == sp {
            print!("]");
        }
    }
    println!();
}

fn read_stdin() -> String {
    let mut input = String::new();
    stdin().read_line(&mut input).unwrap();
    input.trim().into()
}
<commit_msg>Change the stack print format in debug<commit_after>mod command;

use std::io::{stdin, stdout};
use std::io::prelude::*;
use std::borrow::Cow;

use cpu::cpu::Cpu;
use cpu::cpu::GFX_HEIGHT;
use cpu::cpu::GFX_WIDTH;
use self::command::Command;

pub struct Debugger {
    cpu: Cpu,
    last_commad: Option<Command>,
}

impl Debugger {
    pub fn new(cpu: Cpu) -> Debugger {
        Debugger {
            cpu: cpu,
            last_commad: None,
        }
    }

    pub fn run(&mut self) {
        loop {
            print!("chip8> ");
            stdout().flush().unwrap();

            let command = match (read_stdin().parse(), self.last_commad) {
                (Ok(Command::Repeat), Some(c)) => Ok(c),
                (Ok(Command::Repeat), None) => Err("No last command".into()),
                (Ok(c), _) => Ok(c),
                (Err(e), _) => Err(e),
            };

            match command {
                Ok(Command::Step(count)) => self.step(count),
                Ok(Command::Exit) => break,
                Ok(Command::Repeat) => unreachable!(),
                Err(ref e) => println!("{}", e),
            }

            self.last_commad = command.ok();
        }
    }

    pub fn step(&mut self, count: usize) {
        for _ in 0..count {
            let curr_pc = self.cpu.curr_pc();
            let curr_index = self.cpu.curr_index();
            let curr_opcode = self.cpu.curr_opcode();
            let curr_regs = self.cpu.curr_regs();
            let curr_stack = self.cpu.curr_stack();
            let curr_sp = self.cpu.curr_sp();
            let curr_gfx = self.cpu.curr_gfx();

            print!("pc:{:04X},", curr_pc);
            print!("index:{:04X},", curr_index);
            println!("opcode:{:04X}", curr_opcode);
            println!("=============================================");

            println!("stack:");
            print_stack(curr_stack, curr_sp);
            println!("=============================================");
            println!("registers:");
            print_regs(curr_regs);
            println!("=============================================");
            println!("screen:");
            print_gfx(curr_gfx);
            println!("=============================================");

            self.cpu.emulate_cycle();
        }
    }
}

fn print_gfx(gfx: Vec<u8>) {
    for i in 0..GFX_HEIGHT {
        for j in 0..GFX_WIDTH {
            print!("{}", gfx[(i * GFX_WIDTH + j) as usize]);
        }
        println!();
    }
}

fn print_regs(regs: Vec<u8>) {
    println!("| 0| 1| 2| 3| 4| 5| 6| 7| 8| 9| A| B| C| D| E| F|");
    for i in 0..regs.len() {
        print!("|{:02X}", regs[i as usize]);
    }
    println!("|");
}

fn print_stack(stack: Vec<usize>, sp: usize) {
    for i in 0..stack.len() {
        print!("|");
        if i == sp {
            print!("[");
        }
        print!("{:04X}", stack[i as usize]);
        if i == sp {
            print!("]");
        }
    }
    println!("|");
}

fn read_stdin() -> String {
    let mut input = String::new();
    stdin().read_line(&mut input).unwrap();
    input.trim().into()
}
<|endoftext|>