<commit_before>use primal_bit::{BitVec};
use std::{cmp};
use hamming;

use wheel;

mod presieve;

/// A heavily optimised prime sieve.
///
/// This is a streaming segmented sieve, meaning it sieves numbers in
/// intervals, extracting whatever it needs and discarding it. See
/// `Sieve` for a wrapper that caches the information to allow for
/// repeated queries, at the cost of *O(limit)* memory use.
///
/// This uses *O(sqrt(limit))* memory, and is designed to be as
/// cache-friendly as possible. `StreamingSieve` should be used for
/// one-off calls, or simple linear iteration.
///
/// The design is *heavily* inspired/adopted from Kim Walisch's
/// [primesieve](http://primesieve.org/), and has similar speed
/// (around 5-20% slower).
///
/// # Examples
///
/// ```rust
/// # extern crate primal;
/// let count = primal::StreamingSieve::count_upto(123456);
/// println!("𝜋(123456) = {}", count);
/// ```
#[derive(Debug)]
pub struct StreamingSieve {
    small: Option<::Sieve>,
    // stores which numbers *aren't* prime, i.e. true == composite.
    sieve: BitVec,
    primes: Vec<wheel::State<wheel::Wheel210>>,
    small_primes: Vec<wheel::State<wheel::Wheel30>>,
    large_primes: Vec<wheel::State<wheel::Wheel210>>,
    presieve: presieve::Presieve,

    low: usize,
    current: usize,
    limit: usize,
}

const CACHE: usize = 32 << 10;
const SEG_ELEMS: usize = 8 * CACHE;
const SEG_LEN: usize = SEG_ELEMS * wheel::BYTE_MODULO / wheel::BYTE_SIZE;

impl StreamingSieve {
    /// Create a new instance of the streaming sieve that will
    /// correctly progressively filter primes up to `limit`.
    fn new(limit: usize) -> StreamingSieve {
        let low = 0;

        let elems = cmp::min(wheel::bits_for(limit), SEG_ELEMS);
        let presieve = presieve::Presieve::new(elems);
        let current = presieve.smallest_unincluded_prime();

        let small = if limit < current * current {
            None
        } else {
            Some(::Sieve::new((limit as f64).sqrt() as usize + 1))
        };

        StreamingSieve {
            small: small,
            sieve: BitVec::from_elem(elems, false),
            primes: vec![],
            small_primes: vec![],
            large_primes: vec![],
            presieve: presieve,

            low: low,
            current: current,
            limit: limit
        }
    }
    fn split_index(&self, idx: usize) -> (usize, usize) {
        let len = SEG_ELEMS;
        (idx / len,idx % len)
    }
    fn index_for(&self, n: usize) -> (bool, usize, usize) {
        let (b, idx) = wheel::bit_index(n);
        let (base, tweak) = self.split_index(idx);
        (b, base, tweak)
    }

    /// Count the number of primes upto and including `n`, that is, 𝜋,
    /// the [prime counting
    /// function](https://en.wikipedia.org/wiki/Prime-counting_function).
    pub fn count_upto(n: usize) -> usize {
        match n {
            0...1 => 0,
            2 => 1,
            3...4 => 2,
            5...6 => 3,
            7...10 => 4,
            _ => {
                let mut sieve = StreamingSieve::new(n);
                let (includes, base, tweak) = sieve.index_for(n);
                let mut count = match wheel::BYTE_MODULO {
                    30 => 3,
                    _ => unimplemented!()
                };

                for _ in 0..base {
                    let (_, bitv) = sieve.next().unwrap();
                    let bytes = bitv.as_bytes();
                    count += 8 * bytes.len() - hamming::weight(bytes) as usize;
                }
                let (tweak_byte, tweak_bit) = (tweak / 8, tweak % 8);
                let (_, last) = sieve.next().unwrap();
                let bytes = last.as_bytes();
                count += 8 * tweak_byte - hamming::weight(&bytes[..tweak_byte]) as usize;
                if tweak_bit > 0 || includes {
                    let byte = bytes[tweak_byte];
                    for i in 0..tweak_bit + includes as usize {
                        count += (byte & (1 << i) == 0) as usize
                    }
                }
                count
            }
        }
    }

    fn find_new_sieving_primes(&mut self, low: usize, high: usize) {
        if let Some(ref small) = self.small {
            let mut s = self.current;
            assert!(s % 2 == 1);
            while s * s <= high {
                if small.is_prime(s) {
                    if s <= SEG_LEN / 100 {
                        self.small_primes.push(wheel::compute_wheel_elem(wheel::Wheel30, s, low));
                    } else {
                        let elem = wheel::compute_wheel_elem(wheel::Wheel210, s, low);
                        if s < SEG_LEN / 2 {
                            self.primes.push(elem)
                        } else {
                            self.large_primes.push(elem)
                        }
                    }
                }
                s += 2
            }

            self.current = s;
        }
    }

    fn small_primes_sieve<W: wheel::Wheel>(sieve: &mut BitVec,
                                           small_primes: &mut [wheel::State<W>]) {
        let bytes = sieve.as_bytes_mut();
        for wi in small_primes {
            wi.sieve_hardcoded(bytes);
        }
    }

    fn direct_sieve(&mut self) {
        let bytes = self.sieve.as_bytes_mut();

        let mut iter = self.primes.iter_mut();

        while iter.size_hint().0 >= 3 {
            match (iter.next(), iter.next(), iter.next()) {
                (Some(wi1), Some(wi2), Some(wi3)) => {
                    wi1.sieve_triple(wi2, wi3, bytes);
                }
                _ => unreachable!()
            }
        }
        for wi in iter {
            wi.sieve(bytes)
        }
    }

    fn large_primes_sieve(&mut self) {
        let bytes = self.sieve.as_bytes_mut();

        let mut iter = self.large_primes.iter_mut();

        while iter.size_hint().0 >= 2 {
            match (iter.next(), iter.next()) {
                (Some(wi1), Some(wi2)) => {
                    wi1.sieve_pair(wi2, bytes);
                }
                _ => unreachable!()
            }
        }
        for wi in iter {
            wi.sieve(bytes)
        }
    }

    /// Extract the next chunk of filtered primes, the return value is
    /// `Some((low, v))` or `None` if the sieve has reached the limit.
    ///
    /// The vector stores bits for each odd number starting at `low`.
    /// Bit `n` of `v` is set if and only if `low + 2 * n + 1` is
    /// prime.
    ///
    /// NB. the prime 2 is not included in any of these sieves and so
    /// needs special handling.
    fn next(&mut self) -> Option<(usize, &BitVec)> {
        if self.low >= self.limit {
            return None
        }

        let low = self.low;
        self.low += SEG_LEN;
        let high = cmp::min(low + SEG_LEN - 1, self.limit);

        self.find_new_sieving_primes(low, high);

        self.presieve.apply(&mut self.sieve, low);
        StreamingSieve::small_primes_sieve(&mut self.sieve, &mut self.small_primes);
        self.direct_sieve();
        self.large_primes_sieve();

        if low == 0 {
            // 1 is not prime.
            self.sieve.set(0, true);
            self.presieve.mark_small_primes(&mut self.sieve);
        }

        Some((low, &self.sieve))
    }
}

// module-public but crate-private wrappers, to allow `Sieve` to call these functions.
pub fn new(limit: usize) -> StreamingSieve {
    StreamingSieve::new(limit)
}
pub fn next(sieve: &mut StreamingSieve) -> Option<(usize, &BitVec)> {
    sieve.next()
}

#[cfg(test)]
mod tests {
    use wheel;
    use super::StreamingSieve;
    fn gcd(x: usize, y: usize) -> usize {
        if y == 0 { x }
        else { gcd(y, x % y) }
    }
    fn coprime_to(x: usize) -> Vec<usize> {
        (1..x).filter(|&n| gcd(n, x) == 1).collect()
    }
    #[test]
    fn test() {
        let coprime = coprime_to(wheel::BYTE_MODULO);
        const LIMIT: usize = 2_000_000;
        let mut sieve = StreamingSieve::new(LIMIT);
        let primes = ::primal_smallsieve::Primes::sieve(LIMIT);

        let mut base = 0;
        let mut index = 0;

        while let Some((_low, next)) = sieve.next() {
            for val in next {
                let i = wheel::BYTE_MODULO * base + coprime[index];
                if i >= LIMIT { break }
                assert!(primes.is_prime(i) == !val,
                        "failed for {} (is prime = {})", i, primes.is_prime(i));

                index += 1;
                if index == wheel::BYTE_SIZE {
                    index = 0;
                    base += 1
                }
            }
        }
    }
}

#[cfg(all(test, feature = "unstable"))]
mod benches {
    use test::Bencher;
    use super::StreamingSieve;

    fn run(b: &mut Bencher, n: usize) {
        b.iter(|| {
            let mut sieve = StreamingSieve::new(n);
            while sieve.next().is_some() {}
        })
    }

    #[bench]
    fn sieve_small(b: &mut Bencher) {
        run(b, 100)
    }
    #[bench]
    fn sieve_medium(b: &mut Bencher) {
        run(b, 10_000)
    }
    #[bench]
    fn sieve_large(b: &mut Bencher) {
        run(b, 100_000)
    }
    #[bench]
    fn sieve_larger(b: &mut Bencher) {
        run(b, 1_000_000)
    }
    #[bench]
    fn sieve_huge(b: &mut Bencher) {
        run(b, 10_000_000)
    }
}
<commit_msg>sieve: test StreamingSieve::count_upto.<commit_after>use primal_bit::{BitVec};
use std::{cmp};
use hamming;

use wheel;

mod presieve;

/// A heavily optimised prime sieve.
///
/// This is a streaming segmented sieve, meaning it sieves numbers in
/// intervals, extracting whatever it needs and discarding it. See
/// `Sieve` for a wrapper that caches the information to allow for
/// repeated queries, at the cost of *O(limit)* memory use.
///
/// This uses *O(sqrt(limit))* memory, and is designed to be as
/// cache-friendly as possible. `StreamingSieve` should be used for
/// one-off calls, or simple linear iteration.
///
/// The design is *heavily* inspired/adopted from Kim Walisch's
/// [primesieve](http://primesieve.org/), and has similar speed
/// (around 5-20% slower).
///
/// # Examples
///
/// ```rust
/// # extern crate primal;
/// let count = primal::StreamingSieve::count_upto(123456);
/// println!("𝜋(123456) = {}", count);
/// ```
#[derive(Debug)]
pub struct StreamingSieve {
    small: Option<::Sieve>,
    // stores which numbers *aren't* prime, i.e. true == composite.
    sieve: BitVec,
    primes: Vec<wheel::State<wheel::Wheel210>>,
    small_primes: Vec<wheel::State<wheel::Wheel30>>,
    large_primes: Vec<wheel::State<wheel::Wheel210>>,
    presieve: presieve::Presieve,

    low: usize,
    current: usize,
    limit: usize,
}

const CACHE: usize = 32 << 10;
const SEG_ELEMS: usize = 8 * CACHE;
const SEG_LEN: usize = SEG_ELEMS * wheel::BYTE_MODULO / wheel::BYTE_SIZE;

impl StreamingSieve {
    /// Create a new instance of the streaming sieve that will
    /// correctly progressively filter primes up to `limit`.
    fn new(limit: usize) -> StreamingSieve {
        let low = 0;

        let elems = cmp::min(wheel::bits_for(limit), SEG_ELEMS);
        let presieve = presieve::Presieve::new(elems);
        let current = presieve.smallest_unincluded_prime();

        let small = if limit < current * current {
            None
        } else {
            Some(::Sieve::new((limit as f64).sqrt() as usize + 1))
        };

        StreamingSieve {
            small: small,
            sieve: BitVec::from_elem(elems, false),
            primes: vec![],
            small_primes: vec![],
            large_primes: vec![],
            presieve: presieve,

            low: low,
            current: current,
            limit: limit
        }
    }
    fn split_index(&self, idx: usize) -> (usize, usize) {
        let len = SEG_ELEMS;
        (idx / len,idx % len)
    }
    fn index_for(&self, n: usize) -> (bool, usize, usize) {
        let (b, idx) = wheel::bit_index(n);
        let (base, tweak) = self.split_index(idx);
        (b, base, tweak)
    }

    /// Count the number of primes upto and including `n`, that is, 𝜋,
    /// the [prime counting
    /// function](https://en.wikipedia.org/wiki/Prime-counting_function).
    pub fn count_upto(n: usize) -> usize {
        match n {
            0...1 => 0,
            2 => 1,
            3...4 => 2,
            5...6 => 3,
            7...10 => 4,
            _ => {
                let mut sieve = StreamingSieve::new(n);
                let (includes, base, tweak) = sieve.index_for(n);
                let mut count = match wheel::BYTE_MODULO {
                    30 => 3,
                    _ => unimplemented!()
                };

                for _ in 0..base {
                    let (_, bitv) = sieve.next().unwrap();
                    let bytes = bitv.as_bytes();
                    count += 8 * bytes.len() - hamming::weight(bytes) as usize;
                }
                let (tweak_byte, tweak_bit) = (tweak / 8, tweak % 8);
                let (_, last) = sieve.next().unwrap();
                let bytes = last.as_bytes();
                count += 8 * tweak_byte - hamming::weight(&bytes[..tweak_byte]) as usize;
                if tweak_bit > 0 || includes {
                    let byte = bytes[tweak_byte];
                    for i in 0..tweak_bit + includes as usize {
                        count += (byte & (1 << i) == 0) as usize
                    }
                }
                count
            }
        }
    }

    fn find_new_sieving_primes(&mut self, low: usize, high: usize) {
        if let Some(ref small) = self.small {
            let mut s = self.current;
            assert!(s % 2 == 1);
            while s * s <= high {
                if small.is_prime(s) {
                    if s <= SEG_LEN / 100 {
                        self.small_primes.push(wheel::compute_wheel_elem(wheel::Wheel30, s, low));
                    } else {
                        let elem = wheel::compute_wheel_elem(wheel::Wheel210, s, low);
                        if s < SEG_LEN / 2 {
                            self.primes.push(elem)
                        } else {
                            self.large_primes.push(elem)
                        }
                    }
                }
                s += 2
            }

            self.current = s;
        }
    }

    fn small_primes_sieve<W: wheel::Wheel>(sieve: &mut BitVec,
                                           small_primes: &mut [wheel::State<W>]) {
        let bytes = sieve.as_bytes_mut();
        for wi in small_primes {
            wi.sieve_hardcoded(bytes);
        }
    }

    fn direct_sieve(&mut self) {
        let bytes = self.sieve.as_bytes_mut();

        let mut iter = self.primes.iter_mut();

        while iter.size_hint().0 >= 3 {
            match (iter.next(), iter.next(), iter.next()) {
                (Some(wi1), Some(wi2), Some(wi3)) => {
                    wi1.sieve_triple(wi2, wi3, bytes);
                }
                _ => unreachable!()
            }
        }
        for wi in iter {
            wi.sieve(bytes)
        }
    }

    fn large_primes_sieve(&mut self) {
        let bytes = self.sieve.as_bytes_mut();

        let mut iter = self.large_primes.iter_mut();

        while iter.size_hint().0 >= 2 {
            match (iter.next(), iter.next()) {
                (Some(wi1), Some(wi2)) => {
                    wi1.sieve_pair(wi2, bytes);
                }
                _ => unreachable!()
            }
        }
        for wi in iter {
            wi.sieve(bytes)
        }
    }

    /// Extract the next chunk of filtered primes, the return value is
    /// `Some((low, v))` or `None` if the sieve has reached the limit.
    ///
    /// The vector stores bits for each odd number starting at `low`.
    /// Bit `n` of `v` is set if and only if `low + 2 * n + 1` is
    /// prime.
    ///
    /// NB. the prime 2 is not included in any of these sieves and so
    /// needs special handling.
    fn next(&mut self) -> Option<(usize, &BitVec)> {
        if self.low >= self.limit {
            return None
        }

        let low = self.low;
        self.low += SEG_LEN;
        let high = cmp::min(low + SEG_LEN - 1, self.limit);

        self.find_new_sieving_primes(low, high);

        self.presieve.apply(&mut self.sieve, low);
        StreamingSieve::small_primes_sieve(&mut self.sieve, &mut self.small_primes);
        self.direct_sieve();
        self.large_primes_sieve();

        if low == 0 {
            // 1 is not prime.
            self.sieve.set(0, true);
            self.presieve.mark_small_primes(&mut self.sieve);
        }

        Some((low, &self.sieve))
    }
}

// module-public but crate-private wrappers, to allow `Sieve` to call these functions.
pub fn new(limit: usize) -> StreamingSieve {
    StreamingSieve::new(limit)
}
pub fn next(sieve: &mut StreamingSieve) -> Option<(usize, &BitVec)> {
    sieve.next()
}

#[cfg(test)]
mod tests {
    use primal_smallsieve::Primes;
    use wheel;
    use super::StreamingSieve;
    fn gcd(x: usize, y: usize) -> usize {
        if y == 0 { x }
        else { gcd(y, x % y) }
    }
    fn coprime_to(x: usize) -> Vec<usize> {
        (1..x).filter(|&n| gcd(n, x) == 1).collect()
    }
    #[test]
    fn test() {
        let coprime = coprime_to(wheel::BYTE_MODULO);
        const LIMIT: usize = 2_000_000;
        let mut sieve = StreamingSieve::new(LIMIT);
        let primes = ::primal_smallsieve::Primes::sieve(LIMIT);

        let mut base = 0;
        let mut index = 0;

        while let Some((_low, next)) = sieve.next() {
            for val in next {
                let i = wheel::BYTE_MODULO * base + coprime[index];
                if i >= LIMIT { break }
                assert!(primes.is_prime(i) == !val,
                        "failed for {} (is prime = {})", i, primes.is_prime(i));

                index += 1;
                if index == wheel::BYTE_SIZE {
                    index = 0;
                    base += 1
                }
            }
        }
    }
    #[test]
    fn count_upto() {
        let limit = 2_000_000;
        let real = Primes::sieve(limit);

        for i in (0..20).chain((0..100).map(|n| n * 19998 + 1)) {
            let val = StreamingSieve::count_upto(i);
            let true_ = real.primes().take_while(|p| *p <= i).count();
            assert!(val == true_, "failed for {}, true {}, computed {}",
                    i, true_, val)
        }
    }
}

#[cfg(all(test, feature = "unstable"))]
mod benches {
    use test::Bencher;
    use super::StreamingSieve;

    fn run(b: &mut Bencher, n: usize) {
        b.iter(|| {
            let mut sieve = StreamingSieve::new(n);
            while sieve.next().is_some() {}
        })
    }

    #[bench]
    fn sieve_small(b: &mut Bencher) {
        run(b, 100)
    }
    #[bench]
    fn sieve_medium(b: &mut Bencher) {
        run(b, 10_000)
    }
    #[bench]
    fn sieve_large(b: &mut Bencher) {
        run(b, 100_000)
    }
    #[bench]
    fn sieve_larger(b: &mut Bencher) {
        run(b, 1_000_000)
    }
    #[bench]
    fn sieve_huge(b: &mut Bencher) {
        run(b, 10_000_000)
    }
}
<|endoftext|>


<commit_before>use std::time::SystemTime;
use std::collections::HashMap;
use std::sync::Arc;
use std::ops::Deref;

use mioco::sync::Mutex;
use trust_dns::rr::{Name, RecordType};
use trust_dns::op::Message;

use utils::MessageExt;

pub type Key = Name;
#[derive(Default)]
pub struct RecordTypeEntry {
    message: Option<Message>,
    expiration: Option<SystemTime>,
}
#[derive(Default)]
pub struct Entry {
    records: HashMap<RecordType, RecordTypeEntry>,
}
impl Entry {
    pub fn lookup(&self, t: RecordType) -> Option<&Message> {
        self.records.get(&t).map_or(None, |x| x.message.as_ref())
    }
    pub fn update(&mut self, msg: &Message) {
        // TODO: Validate message before updating
        // TODO: Expiration
        self.records.insert(msg.get_queries()[0].get_query_type(), RecordTypeEntry {
            message: Some(msg.clone_resp()),
            expiration: None,
        });
    }
}
pub struct CachePlain {
    entries: HashMap<Key, Entry>,
}
pub type CacheInst = Mutex<CachePlain>;

impl CachePlain {
    pub fn lookup(&self, key: &Key) -> Option<&Entry> {
        self.entries.get(key)
    }
    pub fn lookup_or_insert(&mut self, key: &Key) -> &mut Entry {
        self.entries.entry(key.clone()).or_insert_with(Entry::default)
    }
}
pub struct Cache {
    inst: CacheInst,
}
impl Cache {
    pub fn lookup<F, R>(&self, key: &Key, op: F) -> Option<R>
        where F: FnOnce(&Entry) -> R,
    {
        let guard = self.inst.lock().expect("The mutex shouldn't be poisoned");
        guard.lookup(key).map(op)
    }
    pub fn lookup_with_type<F, R>(&self, key: &Key, t: RecordType, op: F) -> Option<R>
        where F: FnOnce(&Message) -> R,
    {
        let guard = self.inst.lock().expect("The mutex shouldn't be poisoned");
        guard.lookup(key).and_then(|entry| entry.lookup(t)).map(op)
    }
    pub fn operate<F, R>(&self, key: &Key, op: F) -> R
        where F: FnOnce(&mut Entry) -> R,
    {
        let mut guard = self.inst.lock().expect("The mutex shouldn't be poisoned");
        op(guard.lookup_or_insert(key))
    }
}
impl Default for Cache {
    fn default() -> Self {
        Cache {
            inst: Mutex::new(CachePlain {
                entries: HashMap::new(),
            }),
        }
    }
}

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

    #[test]
    fn test_cache_case_insensitivity() {
        unimplemented!();
    }
}
<commit_msg>Add an unit test for case insensitivity<commit_after>use std::time::SystemTime;
use std::collections::HashMap;
use std::sync::Arc;
use std::ops::Deref;

use mioco::sync::Mutex;
use trust_dns::rr::{Name, RecordType};
use trust_dns::op::Message;

use utils::MessageExt;

pub type Key = Name;
#[derive(Default)]
pub struct RecordTypeEntry {
    message: Option<Message>,
    expiration: Option<SystemTime>,
}
#[derive(Default)]
pub struct Entry {
    records: HashMap<RecordType, RecordTypeEntry>,
}
impl Entry {
    pub fn lookup(&self, t: RecordType) -> Option<&Message> {
        self.records.get(&t).map_or(None, |x| x.message.as_ref())
    }
    pub fn update(&mut self, msg: &Message) {
        // TODO: Validate message before updating
        // TODO: Expiration
        self.records.insert(msg.get_queries()[0].get_query_type(), RecordTypeEntry {
            message: Some(msg.clone_resp()),
            expiration: None,
        });
    }
}
#[derive(Default)]
pub struct CachePlain {
    entries: HashMap<Key, Entry>,
}
pub type CacheInst = Mutex<CachePlain>;

impl CachePlain {
    pub fn lookup(&self, key: &Key) -> Option<&Entry> {
        self.entries.get(key)
    }
    pub fn lookup_or_insert(&mut self, key: &Key) -> &mut Entry {
        self.entries.entry(key.clone()).or_insert_with(Entry::default)
    }
}
pub struct Cache {
    inst: CacheInst,
}
impl Cache {
    pub fn lookup<F, R>(&self, key: &Key, op: F) -> Option<R>
        where F: FnOnce(&Entry) -> R,
    {
        let guard = self.inst.lock().expect("The mutex shouldn't be poisoned");
        guard.lookup(key).map(op)
    }
    pub fn lookup_with_type<F, R>(&self, key: &Key, t: RecordType, op: F) -> Option<R>
        where F: FnOnce(&Message) -> R,
    {
        let guard = self.inst.lock().expect("The mutex shouldn't be poisoned");
        guard.lookup(key).and_then(|entry| entry.lookup(t)).map(op)
    }
    pub fn operate<F, R>(&self, key: &Key, op: F) -> R
        where F: FnOnce(&mut Entry) -> R,
    {
        let mut guard = self.inst.lock().expect("The mutex shouldn't be poisoned");
        op(guard.lookup_or_insert(key))
    }
}
impl Default for Cache {
    fn default() -> Self {
        Cache {
            inst: Mutex::new(CachePlain {
                entries: HashMap::new(),
            }),
        }
    }
}

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

    fn name(raw: &str) -> Name {
        Name::parse(raw, Some(&Name::root())).unwrap()
    }
    #[test]
    fn test_cache_case_insensitivity() {
        let mut cache = CachePlain::default();
        cache.lookup_or_insert(&name("www.google.com"));
        assert!(cache.lookup(&name("www.google.com")).is_some());
        assert!(cache.lookup(&name("www.baidu.com")).is_none());
        assert!(cache.lookup(&name("wWw.goOgle.coM")).is_some());
    }
}
<|endoftext|>


<commit_before>use std::convert::From;
use std::fmt::Debug;
use std::hash::Hash;
use std::iter::FromIterator;
use std::iter::Iterator;
use std::ops::Deref;

use rand::Rng;
use smallvec::SmallVec;

use units::{RowLength, RowIndex, ColumnLength, ColumnIndex};

pub trait Coordinate: PartialEq + Eq + Hash + Copy + Clone + Debug + Ord + PartialOrd {

    fn from_row_major_index(index: usize, row_size: RowLength, column_size: ColumnLength) -> Self;
    fn from_row_column_indices(col_index: ColumnIndex, row_index: RowIndex) -> Self;
    fn as_cartesian_2d(&self) -> Cartesian2DCoordinate;
}

pub trait Cell {

    type Coord: Coordinate;
    type Direction: Eq + PartialEq + Copy + Clone + Debug;
                          // Require that the Option fixed size Vec specifically wraps Coord with an Option otherwise
                          // we get type errors saying a general CoordinateOptionSmallVec IntoIterator::Item cannot `unwrap`.
                          // associated type specification, not trait type parameter, but almost same syntax...
                          // e.g. FromIterator<T> is a type parameter to the trait
                          //      IntoIterator<Item=T> is an associated type specialisation
                          // Deref<Target=[Self::Coord]> gives access to the `iter` of slices.
    type CoordinateSmallVec: FromIterator<Self::Coord> + Deref<Target=[Self::Coord]>;
    type CoordinateOptionSmallVec: FromIterator<Option<Self::Coord>> + Deref<Target=[Option<Self::Coord>]>;
    type DirectionSmallVec: FromIterator<Self::Direction> + Deref<Target=[Self::Direction]>;

    /// Creates a small vec of the possible directions away from this Cell.
    fn offset_directions(coord: &Option<Self::Coord>) -> Self::DirectionSmallVec;

    /// Creates a new `Coord` offset 1 cell away in the given direction.
    /// Returns None if the Coordinate is not representable.
    fn offset_coordinate(coord: Self::Coord, dir: Self::Direction) -> Option<Self::Coord>;

    fn rand_direction<R: Rng>(rng: &mut R) -> Self::Direction;
    fn rand_roughly_vertical_direction<R: Rng>(rng: &mut R) -> Self::Direction;
    fn rand_roughly_horizontal_direction<R: Rng>(rng: &mut R) -> Self::Direction;
}

#[derive(Hash, Eq, PartialEq, Copy, Clone, Debug, Ord, PartialOrd)]
pub struct Cartesian2DCoordinate {
    pub x: u32,
    pub y: u32,
}

#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum CompassPrimary {
    North,
    South,
    East,
    West,
}

#[derive(Copy, Clone, Debug)]
pub struct SquareCell;

impl Cell for SquareCell {
    type Coord = Cartesian2DCoordinate;  // : Debug, Copy, Clone
    type Direction = CompassPrimary;
    type CoordinateSmallVec = SmallVec<[Self::Coord; 4]>;

    // do not really want this indirection as it requires me to make option itself, unwrapping a trait?
    // prefer the const 4, but they do not exist in the language yet
    // could just dynamically query the size of CoordinateSmallVec? No then the option variant is not a compile time decision
    // argh
    type CoordinateOptionSmallVec = SmallVec<[Option<Self::Coord>; 4]>;

    type DirectionSmallVec = SmallVec<[CompassPrimary; 4]>;

    fn offset_directions(_: &Option<Self::Coord>) -> Self::DirectionSmallVec {
        [CompassPrimary::North,
         CompassPrimary::South,
         CompassPrimary::East,
         CompassPrimary::West]
        .into_iter().cloned().collect::<Self::DirectionSmallVec>()
    }

    fn offset_coordinate(coord: Self::Coord, dir: Self::Direction) -> Option<Self::Coord> {

        let (x, y) = (coord.x, coord.y);
        match dir {
            CompassPrimary::North => {
                if y > 0 {
                    Some(Cartesian2DCoordinate { x: x, y: y - 1 })
                } else {
                    None
                }
            }
            CompassPrimary::South => Some(Cartesian2DCoordinate { x: x, y: y + 1 }),
            CompassPrimary::East => Some(Cartesian2DCoordinate { x: x + 1, y: y }),
            CompassPrimary::West => {
                if x > 0 {
                    Some(Cartesian2DCoordinate { x: x - 1, y: y })
                } else {
                    None
                }
            }
        }
    }

    fn rand_direction<R: Rng>(rng: &mut R) -> Self::Direction {
        const DIRS_COUNT: usize = 4;
        const DIRS: [CompassPrimary; DIRS_COUNT] =
            [CompassPrimary::North, CompassPrimary::South, CompassPrimary::East, CompassPrimary::West];
        let dir_index = rng.gen::<usize>() % DIRS_COUNT;
        DIRS[dir_index]
    }

    fn rand_roughly_vertical_direction<R: Rng>(rng: &mut R) -> Self::Direction {
        if rng.gen() {
            CompassPrimary::North
        } else {
            CompassPrimary::South
        }
    }
    fn rand_roughly_horizontal_direction<R: Rng>(rng: &mut R) -> Self::Direction {
        if rng.gen() {
            CompassPrimary::East
        } else {
            CompassPrimary::West
        }
    }
}

impl Cartesian2DCoordinate {
    pub fn new(x: u32, y: u32) -> Cartesian2DCoordinate {
        Cartesian2DCoordinate { x: x, y: y }
    }
}
impl Coordinate for Cartesian2DCoordinate {

    fn from_row_major_index(index: usize, row_size: RowLength, _: ColumnLength) -> Cartesian2DCoordinate {
        let RowLength(width) = row_size;
        let x = index % width;
        let y = index / width;

        Cartesian2DCoordinate::new(x as u32, y as u32)
    }

    fn from_row_column_indices(col_index: ColumnIndex, row_index: RowIndex) -> Self {
        let (ColumnIndex(col), RowIndex(row)) = (col_index, row_index);
        Cartesian2DCoordinate::new(col as u32, row as u32)
    }

    fn as_cartesian_2d(&self) -> Cartesian2DCoordinate {
        *self
    }
}

impl From<(u32, u32)> for Cartesian2DCoordinate {
    fn from(x_y_pair: (u32, u32)) -> Cartesian2DCoordinate {
        Cartesian2DCoordinate::new(x_y_pair.0, x_y_pair.1)
    }
}

#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub struct PolarCell;

#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum ClockDirection {
    Clockwise,
    CounterClockwise,
    Inward,
    Outward
}

impl Cell for PolarCell {

    type Coord = Cartesian2DCoordinate;
    type Direction = ClockDirection;
    type CoordinateSmallVec = SmallVec<[Self::Coord; 8]>;
    type CoordinateOptionSmallVec = SmallVec<[Option<Self::Coord>; 8]>;
    type DirectionSmallVec = SmallVec<[Self::Direction; 8]>;

    /// Creates a small vec of the possible directions away from this Cell.
    fn offset_directions(_: &Option<Self::Coord>) -> Self::DirectionSmallVec {
        [ClockDirection::Clockwise,
         ClockDirection::CounterClockwise,
         ClockDirection::Inward,
         ClockDirection::Outward]
        .into_iter().cloned().collect::<Self::DirectionSmallVec>()

        // and extend from the outward direction instance? [ClockDirection::Outward, ClockDirection::Outward, ClockDirection::Outward]?
    }

    /// Creates a new `Coord` offset 1 cell away in the given direction.
    /// Returns None if the Coordinate is not representable.
    fn offset_coordinate(_: Self::Coord, dir: Self::Direction) -> Option<Self::Coord> {

        //let (x, y) = (coord.x, coord.y);
        match dir {
            ClockDirection::Clockwise => {

            }
            ClockDirection::CounterClockwise => {},
            ClockDirection::Inward => {},
            ClockDirection::Outward => {

            }
        };

        None
    }

    fn rand_direction<R: Rng>(rng: &mut R) -> Self::Direction { // what about multiple outward options? outward is not a single direction
        const DIRS_COUNT: usize = 4;
        const DIRS: [ClockDirection; DIRS_COUNT] =
            [ClockDirection::Clockwise, ClockDirection::CounterClockwise, ClockDirection::Inward, ClockDirection::Outward];
        let dir_index = rng.gen::<usize>() % DIRS_COUNT;
        DIRS[dir_index]
    }

    fn rand_roughly_vertical_direction<R: Rng>(rng: &mut R) -> Self::Direction {
        if rng.gen() {
            ClockDirection::Clockwise
        } else {
            ClockDirection::CounterClockwise
        }
    }

    fn rand_roughly_horizontal_direction<R: Rng>(rng: &mut R) -> Self::Direction {
        if rng.gen() {
            ClockDirection::Inward
        } else {
            ClockDirection::Outward
        }
    }

}

// Polar grid constructor
// number of rows, assume "columns" is 1, which will be adaptively subdivided.
// so need a RectGrid where can specify the rows and columns

<commit_msg>refactor notes<commit_after>use std::convert::From;
use std::fmt::Debug;
use std::hash::Hash;
use std::iter::FromIterator;
use std::iter::Iterator;
use std::ops::Deref;

use rand::Rng;
use smallvec::SmallVec;

use units::{RowLength, RowIndex, ColumnLength, ColumnIndex};

pub trait Coordinate: PartialEq + Eq + Hash + Copy + Clone + Debug + Ord + PartialOrd {

    fn from_row_major_index(index: usize, row_size: RowLength, column_size: ColumnLength) -> Self;
    fn from_row_column_indices(col_index: ColumnIndex, row_index: RowIndex) -> Self;
    fn as_cartesian_2d(&self) -> Cartesian2DCoordinate;
}

pub trait Cell {

    type Coord: Coordinate;
    type Direction: Eq + PartialEq + Copy + Clone + Debug;
                          // Require that the Option fixed size Vec specifically wraps Coord with an Option otherwise
                          // we get type errors saying a general CoordinateOptionSmallVec IntoIterator::Item cannot `unwrap`.
                          // associated type specification, not trait type parameter, but almost same syntax...
                          // e.g. FromIterator<T> is a type parameter to the trait
                          //      IntoIterator<Item=T> is an associated type specialisation
                          // Deref<Target=[Self::Coord]> gives access to the `iter` of slices.
    type CoordinateSmallVec: FromIterator<Self::Coord> + Deref<Target=[Self::Coord]>;
    type CoordinateOptionSmallVec: FromIterator<Option<Self::Coord>> + Deref<Target=[Option<Self::Coord>]>;
    type DirectionSmallVec: FromIterator<Self::Direction> + Deref<Target=[Self::Direction]>;

    /// Creates a small vec of the possible directions away from this Cell.
    fn offset_directions(coord: &Option<Self::Coord>) -> Self::DirectionSmallVec;

    /// Creates a new `Coord` offset 1 cell away in the given direction.
    /// Returns None if the Coordinate is not representable.
    fn offset_coordinate(coord: Self::Coord, dir: Self::Direction) -> Option<Self::Coord>;

    fn rand_direction<R: Rng>(rng: &mut R) -> Self::Direction;
    fn rand_roughly_vertical_direction<R: Rng>(rng: &mut R) -> Self::Direction;
    fn rand_roughly_horizontal_direction<R: Rng>(rng: &mut R) -> Self::Direction;
}

#[derive(Hash, Eq, PartialEq, Copy, Clone, Debug, Ord, PartialOrd)]
pub struct Cartesian2DCoordinate {
    pub x: u32,
    pub y: u32,
}

#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum CompassPrimary {
    North,
    South,
    East,
    West,
}

#[derive(Copy, Clone, Debug)]
pub struct SquareCell;

impl Cell for SquareCell {
    type Coord = Cartesian2DCoordinate;  // : Debug, Copy, Clone
    type Direction = CompassPrimary;
    type CoordinateSmallVec = SmallVec<[Self::Coord; 4]>;

    // do not really want this indirection as it requires me to make option itself, unwrapping a trait?
    // prefer the const 4, but they do not exist in the language yet
    // could just dynamically query the size of CoordinateSmallVec? No then the option variant is not a compile time decision
    // argh
    type CoordinateOptionSmallVec = SmallVec<[Option<Self::Coord>; 4]>;

    type DirectionSmallVec = SmallVec<[CompassPrimary; 4]>;

    fn offset_directions(_: &Option<Self::Coord>) -> Self::DirectionSmallVec {
        [CompassPrimary::North,
         CompassPrimary::South,
         CompassPrimary::East,
         CompassPrimary::West]
        .into_iter().cloned().collect::<Self::DirectionSmallVec>()
    }

    fn offset_coordinate(coord: Self::Coord, dir: Self::Direction) -> Option<Self::Coord> {

        let (x, y) = (coord.x, coord.y);
        match dir {
            CompassPrimary::North => {
                if y > 0 {
                    Some(Cartesian2DCoordinate { x: x, y: y - 1 })
                } else {
                    None
                }
            }
            CompassPrimary::South => Some(Cartesian2DCoordinate { x: x, y: y + 1 }),
            CompassPrimary::East => Some(Cartesian2DCoordinate { x: x + 1, y: y }),
            CompassPrimary::West => {
                if x > 0 {
                    Some(Cartesian2DCoordinate { x: x - 1, y: y })
                } else {
                    None
                }
            }
        }
    }

    fn rand_direction<R: Rng>(rng: &mut R) -> Self::Direction {
        const DIRS_COUNT: usize = 4;
        const DIRS: [CompassPrimary; DIRS_COUNT] =
            [CompassPrimary::North, CompassPrimary::South, CompassPrimary::East, CompassPrimary::West];
        let dir_index = rng.gen::<usize>() % DIRS_COUNT;
        DIRS[dir_index]
    }

    fn rand_roughly_vertical_direction<R: Rng>(rng: &mut R) -> Self::Direction {
        if rng.gen() {
            CompassPrimary::North
        } else {
            CompassPrimary::South
        }
    }
    fn rand_roughly_horizontal_direction<R: Rng>(rng: &mut R) -> Self::Direction {
        if rng.gen() {
            CompassPrimary::East
        } else {
            CompassPrimary::West
        }
    }
}

impl Cartesian2DCoordinate {
    pub fn new(x: u32, y: u32) -> Cartesian2DCoordinate {
        Cartesian2DCoordinate { x: x, y: y }
    }
}
impl Coordinate for Cartesian2DCoordinate {

    fn from_row_major_index(index: usize, row_size: RowLength, _: ColumnLength) -> Cartesian2DCoordinate {
        let RowLength(width) = row_size;
        let x = index % width;
        let y = index / width;

        Cartesian2DCoordinate::new(x as u32, y as u32)
    }

    fn from_row_column_indices(col_index: ColumnIndex, row_index: RowIndex) -> Self {
        let (ColumnIndex(col), RowIndex(row)) = (col_index, row_index);
        Cartesian2DCoordinate::new(col as u32, row as u32)
    }

    fn as_cartesian_2d(&self) -> Cartesian2DCoordinate {
        *self
    }
}

impl From<(u32, u32)> for Cartesian2DCoordinate {
    fn from(x_y_pair: (u32, u32)) -> Cartesian2DCoordinate {
        Cartesian2DCoordinate::new(x_y_pair.0, x_y_pair.1)
    }
}

#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub struct PolarCell;

#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum ClockDirection {
    Clockwise,
    CounterClockwise,
    Inward,
    Outward //(u8) // 0, 1
}

impl Cell for PolarCell {

    type Coord = Cartesian2DCoordinate;
    type Direction = ClockDirection;
    type CoordinateSmallVec = SmallVec<[Self::Coord; 8]>;
    type CoordinateOptionSmallVec = SmallVec<[Option<Self::Coord>; 8]>;
    type DirectionSmallVec = SmallVec<[Self::Direction; 8]>;

    /// Creates a small vec of the possible directions away from this Cell.
    fn offset_directions(_: &Option<Self::Coord>) -> Self::DirectionSmallVec {
        [ClockDirection::Clockwise,
         ClockDirection::CounterClockwise,
         ClockDirection::Inward,
         ClockDirection::Outward]
        .into_iter().cloned().collect::<Self::DirectionSmallVec>()

        // and extend from the outward direction instance? [ClockDirection::Outward, ClockDirection::Outward, ClockDirection::Outward]?
    }

    /// Creates a new `Coord` offset 1 cell away in the given direction.
    /// Returns None if the Coordinate is not representable.
    fn offset_coordinate(_: Self::Coord, dir: Self::Direction) -> Option<Self::Coord> {

        //let (x, y) = (coord.x, coord.y);
        match dir {
            ClockDirection::Clockwise => {

            }
            ClockDirection::CounterClockwise => {},
            ClockDirection::Inward => {},
            ClockDirection::Outward => {

            }
        };

        None
    }

    fn rand_direction<R: Rng>(rng: &mut R) -> Self::Direction { // what about multiple outward options? outward is not a single direction
        const DIRS_COUNT: usize = 4;
        const DIRS: [ClockDirection; DIRS_COUNT] =
            [ClockDirection::Clockwise, ClockDirection::CounterClockwise, ClockDirection::Inward, ClockDirection::Outward];
        let dir_index = rng.gen::<usize>() % DIRS_COUNT;
        DIRS[dir_index]
    }

    fn rand_roughly_vertical_direction<R: Rng>(rng: &mut R) -> Self::Direction {
        if rng.gen() {
            ClockDirection::Clockwise
        } else {
            ClockDirection::CounterClockwise
        }
    }

    fn rand_roughly_horizontal_direction<R: Rng>(rng: &mut R) -> Self::Direction {
        if rng.gen() {
            ClockDirection::Inward
        } else {
            ClockDirection::Outward
        }
    }

}

// Polar grid constructor
// For any coord[x][y]
// what are the neighbours? - what coordinates and handle outward[n]
// what is the corresponding graph index?
// coord.x
// coord.y            // grid config data access - number of rings
// row_height = 1.0 / grid.rows_count     # e.g. row 1. 0.25
// radius = y * (row_height as float)     # 0.25
// circumference = 2 * pi * radius        # 1.5707

// previous_rows_count = .. # 1
// cell_width_if_using_same_cell_count_as_previous_ring = circumference / previous_rows_count  # 1.5707
// ratio = round to nearest number (cell_width_if_using_same_cell_count_as_previous_ring / row_height)  # 6.28 -> 6.0

// cells = previous_rows_count * ratio # 6

// // now we know the cell count in the ring
// // varying cell counts per row
// // coord[x][y]
// // statically the row length is unknown, but the number of rings is fixed when creating the grid.
// // ok, so now we know the row length...
// for any cell on the row, if not row 0 (only 1 cell)
// cw = coord[x+1][y]
// ccw = coord[x-1][y] (wrapping around?)
// // what is previous row length ?
// ratio = row_length / previous_row_length
// parent = cell[x/ratio][y-1]
// parent.outward += this // so to calculate outward of *this*, argh...
// inward = parent // easy to calc inward

// Data needed:
// - number of rows (y height) of the grid
// - row length of previous row [y-1], which varies on each ring - so length of all rows
//   same as current row or half the length
// - outward cells??? max 2 parents per cell I think. If 1 parent then cell count is the same as current row.
//                    if 2 parents then 2 * current rows cells count and outward = [x * 2][y+1] and [(x*2)+1][y+1]
//
// *so row lengths and number of rows is most pertinent*

// - `offset_directions` needs this data to know how many outward cells there are
// - `offset_coordinate` needs to calculate inward, which could be done by knowing how many inward cells there are
//                       Clockwise/CounterClockwise need to know row length to wrap or not allow wrapping.
// where to store grid rows count and length of each row?

// How to map coordinate to graph index? Need new coordinate type to have a different mapping function.
// coord[x][y] == ? Also needs to look up the length of each row. Might be nice to prefix sum the row lengths at each point.
// The lengths need to be calced once at, presumably at a similar time to when we decide the number of nodes in the graph.
//
// refactoring `Grid` (?) for Polar
// rows: RowsCount,
// columns: ColumnsCount,
// still need these but the user should not be providing columns as an argument, or it should be ignored
// - additional data required for rowLengths
// - cells count needs deciding before creating the graph and adding nodes.
// - `size` = (rows * columns) must be customised
// - `random_cell` assumes a fixed row*col size, but the dimension vary.
// - `grid_coordinate_to_index` assumes a fixed row*col size
// - `CellIter` assumes a fixed row*col size
<|endoftext|>


<commit_before>//! Checks if an AST is valid

use ast::*;
use visit::*;

pub struct CheckError {
    msg: &'static str,
    detail: String,
}

fn mkerr(msg: &'static str, detail: String) -> CheckError {
    CheckError {
        msg: msg,
        detail: detail,
    }
}

/// Checks that the passed block contains only valid statements.
pub fn check_block(block: &Block) -> Result<(), CheckError> {
    Err(mkerr("test", "detail".to_string()))
}
<commit_msg>Some work on check.rs<commit_after>//! Checks if an AST is valid

use ast::*;
use visit::*;

pub struct CheckError {
    msg: &'static str,
    detail: String,
}

fn mkerr(msg: &'static str, detail: String) -> CheckError {
    CheckError {
        msg: msg,
        detail: detail,
    }
}

struct Checker {
    res: Result<(), CheckError>,
    forlvl: u32,
}

impl Visitor for Checker {
    fn visit_stmt(&mut self, s: &mut Stmt) {
        if let Ok(..) {
            self.res = match *s {
                SBreak => {
                    if self.forlvl == 0 {
                        Err(mkerr("Use of `break` outside of for loop"))
                    } else { Ok(()) }
                },
                _ => { Ok(()) },
            };

            walk_stmt(s, self);
        }
    }
}

/// Checks that the passed block contains only valid statements.
pub fn check_block(block: &mut Block) -> Result<(), CheckError> {
    let ch = Checker {
        res: Ok(()),
        forlvl: 0,
    };
    walk_block(block, &mut ch);
    ch.res
}

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

    #[test]
    fn test() {
        assert!(check_block(block("break")).is_err());
    }
}
<|endoftext|>


<commit_before>use std::rc::{self, Rc};
use std::sync::{self, Arc};

/// Trait for generalizing downgrading a strong reference to a weak reference.
pub trait Downgrade
where
    Self: Sized,
{
    /// Weak reference type.
    type Weak;

    /// Downgrade to a weak reference.
    fn downgrade(&self) -> Self::Weak;
}

/// Trait for generalizing upgrading a weak reference to a strong reference.
pub trait Upgrade
where
    Self: Sized,
{
    /// Strong reference type.
    type Strong;

    /// Try upgrading a weak reference to a strong reference.
    fn upgrade(&self) -> Option<Self::Strong>;
}

impl<T: Downgrade + crate::ObjectType> Upgrade for crate::WeakRef<T> {
    type Strong = T;

    fn upgrade(&self) -> Option<Self::Strong> {
        self.upgrade()
    }
}

impl<T> Downgrade for Arc<T> {
    type Weak = sync::Weak<T>;

    fn downgrade(&self) -> Self::Weak {
        Arc::downgrade(self)
    }
}

impl<T> Upgrade for sync::Weak<T> {
    type Strong = Arc<T>;

    fn upgrade(&self) -> Option<Self::Strong> {
        self.upgrade()
    }
}

impl<T> Downgrade for Rc<T> {
    type Weak = rc::Weak<T>;

    fn downgrade(&self) -> Self::Weak {
        Rc::downgrade(self)
    }
}

impl<T> Upgrade for rc::Weak<T> {
    type Strong = Rc<T>;

    fn upgrade(&self) -> Option<Self::Strong> {
        self.upgrade()
    }
}

#[doc(hidden)]
#[macro_export]
macro_rules! to_type_before {
    (_) => ();
    (self) => (
        compile_error!("Can't use `self` as variable name for the `clone!` macro. Try storing it in a temporary variable.");
    );
    (@weak self) => (
        compile_error!("Can't use `self` as variable name for the `clone!` macro. Try storing it in a temporary variable.");
    );
    (@strong self) => (
        compile_error!("Can't use `self` as variable name for the `clone!` macro. Try storing it in a temporary variable.");
    );
    ($variable:ident) => (
        compile_error!("You need to specify if this is a weak or a strong clone.");
    );
    (@strong $variable:ident) => (
        let $variable = $variable.clone();
    );
    (@weak $variable:ident) => (
        let $variable = $crate::clone::Downgrade::downgrade(&$variable);
    );
    (@ $keyword:ident $variable:ident) => (
        compile_error!("Unknown keyword, only `weak` and `strong` are allowed");
    );
}

#[doc(hidden)]
#[macro_export]
macro_rules! to_type_after {
    (@weak self, $return_value:expr) => {};
    (@strong self, $return_value:expr) => {};
    (@default-panic, @weak $variable:ident) => {
        let $variable = match $crate::clone::Upgrade::upgrade(&$variable) {
            Some(val) => val,
            None => panic!("failed to upgrade {}", stringify!($variable)),
        };
    };
    (@default-panic, @strong $variable:ident) => {};
    (@weak $variable:ident , $return_value:expr) => {
        let $variable = match $crate::clone::Upgrade::upgrade(&$variable) {
            Some(val) => val,
            None => return ($return_value)(),
        };
    };
    (@strong $variable:ident , $return_value:expr) => {};
    (@ $keyword:ident $variable:ident, $return_value:expr) => {};
}

#[doc(hidden)]
#[macro_export]
macro_rules! to_return_value {
    () => {
        ()
    };
    ($value:expr) => {
        $value
    };
}

/// Macro for passing variables as strong or weak references into a closure.
///
/// This macro can be useful in combination with closures, e.g. signal handlers, to reduce the
/// boilerplate required for passing strong or weak references into the closure. It will
/// automatically create the new reference and pass it with the same name into the closure.
///
/// If upgrading the weak reference to a strong reference inside the closure is failing, the
/// closure is immediately returning an optional default return value. If none is provided, `()` is
/// returned.
///
/// ### Passing a strong reference
///
/// ```
/// use glib::clone;
/// use std::rc::Rc;
///
/// let v = Rc::new(1);
/// let closure = clone!(@strong v => move |x| {
///     println!("v: {}, x: {}", v, x);
/// });
///
/// closure(2);
/// ```
///
/// ### Passing a strong and weak reference
///
/// ```
/// use glib::clone;
/// use std::rc::Rc;
///
/// let v = Rc::new(1);
/// let u = Rc::new(2);
/// let closure = clone!(@strong v, @weak u => move |x| {
///     println!("v: {}, u: {}, x: {}", v, u, x);
/// });
///
/// closure(3);
/// ```
///
/// ### Providing a default return value if upgrading a weak reference fails
///
/// You can do it in two different ways:
///
/// Either by providing the value yourself using `@default-return`:
///
/// ```
/// use glib::clone;
/// use std::rc::Rc;
///
/// let v = Rc::new(1);
/// let closure = clone!(@weak v => @default-return false, move |x| {
///     println!("v: {}, x: {}", v, x);
///     true
/// });
///
/// // Drop value so that the weak reference can't be upgraded.
/// drop(v);
///
/// assert_eq!(closure(2), false);
/// ```
///
/// Or by using `@default-panic` (if the value fails to get upgraded, it'll panic):
///
/// ```run_fail
/// # use glib::clone;
/// # use std::rc::Rc;
/// # let v = Rc::new(1);
/// let closure = clone!(@weak v => @default-panic, move |x| {
///     println!("v: {}, x: {}", v, x);
///     true
/// });
/// # drop(v);
/// # assert_eq!(closure(2), false);
/// ```
///
/// ### Errors
///
/// Here is a list of errors you might encounter:
///
/// **Missing `@weak` or `@strong`**:
///
/// ```compile_fail
/// # use glib::clone;
/// # use std::rc::Rc;
/// let v = Rc::new(1);
///
/// let closure = clone!(v => move |x| {
///     println!("v: {}, x: {}", v, x);
/// });
/// ```
///
/// **Passing `self` as an argument**:
///
/// ```compile_fail
/// # use glib::clone;
/// # use std::rc::Rc;
/// struct Foo;
///
/// impl Foo {
///     fn foo(&self) {
///         let v = Rc::new(1);
///
///         let closure = clone!(@strong self => move |x| {
///             println!("v: {}, x: {}", v, x);
///         });
///     }
/// }
#[macro_export]
macro_rules! clone {
    ($($(@ $strength:ident)? $variables:ident),+ => @default-panic, move || $body:block ) => (
        {
            $( $crate::to_type_before!($(@ $strength)? $variables); )*
            move || {
                $( $crate::to_type_after!(@default-panic, $(@ $strength)? $variables );)*
                $body
            }
        }
    );
    ($($(@ $strength:ident)? $variables:ident),+ => $(@default-return $return_value:expr,)? move || $body:block ) => (
        {
            $( $crate::to_type_before!($(@ $strength)? $variables); )*
            move || {
                let return_value = || $crate::to_return_value!($($return_value)?);
                $( $crate::to_type_after!($(@ $strength)? $variables, return_value );)*
                $body
            }
        }
    );
    ($($(@ $strength:ident)? $variables:ident),+ => @default-panic, move | $($pattern:pat),* | $body:block ) => (
        {
            $( $crate::to_type_before!($(@ $strength)? $variables); )*
            move |$($pattern),*| {
                $( $crate::to_type_after!(@default-panic, $(@ $strength)? $variables, return_value );)*
                $body
            }
        }
    );
    ($($(@ $strength:ident)? $variables:ident),+ => $(@default-return $return_value:expr,)? move | $($pattern:pat),* | $body:block ) => (
        {
            $( $crate::to_type_before!($(@ $strength)? $variables); )*
            move |$($pattern),*| {
                let return_value = || $crate::to_return_value!($($return_value)?);
                $( $crate::to_type_after!($(@ $strength)? $variables, return_value );)*
                $body
            }
        }
    );
}
<commit_msg>Fix handling of @default-panic in macro expansions<commit_after>use std::rc::{self, Rc};
use std::sync::{self, Arc};

/// Trait for generalizing downgrading a strong reference to a weak reference.
pub trait Downgrade
where
    Self: Sized,
{
    /// Weak reference type.
    type Weak;

    /// Downgrade to a weak reference.
    fn downgrade(&self) -> Self::Weak;
}

/// Trait for generalizing upgrading a weak reference to a strong reference.
pub trait Upgrade
where
    Self: Sized,
{
    /// Strong reference type.
    type Strong;

    /// Try upgrading a weak reference to a strong reference.
    fn upgrade(&self) -> Option<Self::Strong>;
}

impl<T: Downgrade + crate::ObjectType> Upgrade for crate::WeakRef<T> {
    type Strong = T;

    fn upgrade(&self) -> Option<Self::Strong> {
        self.upgrade()
    }
}

impl<T> Downgrade for Arc<T> {
    type Weak = sync::Weak<T>;

    fn downgrade(&self) -> Self::Weak {
        Arc::downgrade(self)
    }
}

impl<T> Upgrade for sync::Weak<T> {
    type Strong = Arc<T>;

    fn upgrade(&self) -> Option<Self::Strong> {
        self.upgrade()
    }
}

impl<T> Downgrade for Rc<T> {
    type Weak = rc::Weak<T>;

    fn downgrade(&self) -> Self::Weak {
        Rc::downgrade(self)
    }
}

impl<T> Upgrade for rc::Weak<T> {
    type Strong = Rc<T>;

    fn upgrade(&self) -> Option<Self::Strong> {
        self.upgrade()
    }
}

#[doc(hidden)]
#[macro_export]
macro_rules! to_type_before {
    (_) => ();
    (self) => (
        compile_error!("Can't use `self` as variable name for the `clone!` macro. Try storing it in a temporary variable.");
    );
    (@weak self) => (
        compile_error!("Can't use `self` as variable name for the `clone!` macro. Try storing it in a temporary variable.");
    );
    (@strong self) => (
        compile_error!("Can't use `self` as variable name for the `clone!` macro. Try storing it in a temporary variable.");
    );
    ($variable:ident) => (
        compile_error!("You need to specify if this is a weak or a strong clone.");
    );
    (@strong $variable:ident) => (
        let $variable = $variable.clone();
    );
    (@weak $variable:ident) => (
        let $variable = $crate::clone::Downgrade::downgrade(&$variable);
    );
    (@ $keyword:ident $variable:ident) => (
        compile_error!("Unknown keyword, only `weak` and `strong` are allowed");
    );
}

#[doc(hidden)]
#[macro_export]
macro_rules! to_type_after {
    (@weak self, $return_value:expr) => {};
    (@strong self, $return_value:expr) => {};
    (@default-panic, @weak $variable:ident) => {
        let $variable = match $crate::clone::Upgrade::upgrade(&$variable) {
            Some(val) => val,
            None => panic!("failed to upgrade {}", stringify!($variable)),
        };
    };
    (@default-panic, @strong $variable:ident) => {};
    (@weak $variable:ident , $return_value:expr) => {
        let $variable = match $crate::clone::Upgrade::upgrade(&$variable) {
            Some(val) => val,
            None => return ($return_value)(),
        };
    };
    (@strong $variable:ident , $return_value:expr) => {};
    (@ $keyword:ident $variable:ident, $return_value:expr) => {};
}

#[doc(hidden)]
#[macro_export]
macro_rules! to_return_value {
    () => {
        ()
    };
    ($value:expr) => {
        $value
    };
}

/// Macro for passing variables as strong or weak references into a closure.
///
/// This macro can be useful in combination with closures, e.g. signal handlers, to reduce the
/// boilerplate required for passing strong or weak references into the closure. It will
/// automatically create the new reference and pass it with the same name into the closure.
///
/// If upgrading the weak reference to a strong reference inside the closure is failing, the
/// closure is immediately returning an optional default return value. If none is provided, `()` is
/// returned.
///
/// ### Passing a strong reference
///
/// ```
/// use glib::clone;
/// use std::rc::Rc;
///
/// let v = Rc::new(1);
/// let closure = clone!(@strong v => move |x| {
///     println!("v: {}, x: {}", v, x);
/// });
///
/// closure(2);
/// ```
///
/// ### Passing a strong and weak reference
///
/// ```
/// use glib::clone;
/// use std::rc::Rc;
///
/// let v = Rc::new(1);
/// let u = Rc::new(2);
/// let closure = clone!(@strong v, @weak u => move |x| {
///     println!("v: {}, u: {}, x: {}", v, u, x);
/// });
///
/// closure(3);
/// ```
///
/// ### Providing a default return value if upgrading a weak reference fails
///
/// You can do it in two different ways:
///
/// Either by providing the value yourself using `@default-return`:
///
/// ```
/// use glib::clone;
/// use std::rc::Rc;
///
/// let v = Rc::new(1);
/// let closure = clone!(@weak v => @default-return false, move |x| {
///     println!("v: {}, x: {}", v, x);
///     true
/// });
///
/// // Drop value so that the weak reference can't be upgraded.
/// drop(v);
///
/// assert_eq!(closure(2), false);
/// ```
///
/// Or by using `@default-panic` (if the value fails to get upgraded, it'll panic):
///
/// ```run_fail
/// # use glib::clone;
/// # use std::rc::Rc;
/// # let v = Rc::new(1);
/// let closure = clone!(@weak v => @default-panic, move |x| {
///     println!("v: {}, x: {}", v, x);
///     true
/// });
/// # drop(v);
/// # assert_eq!(closure(2), false);
/// ```
///
/// ### Errors
///
/// Here is a list of errors you might encounter:
///
/// **Missing `@weak` or `@strong`**:
///
/// ```compile_fail
/// # use glib::clone;
/// # use std::rc::Rc;
/// let v = Rc::new(1);
///
/// let closure = clone!(v => move |x| {
///     println!("v: {}, x: {}", v, x);
/// });
/// ```
///
/// **Passing `self` as an argument**:
///
/// ```compile_fail
/// # use glib::clone;
/// # use std::rc::Rc;
/// struct Foo;
///
/// impl Foo {
///     fn foo(&self) {
///         let v = Rc::new(1);
///
///         let closure = clone!(@strong self => move |x| {
///             println!("v: {}, x: {}", v, x);
///         });
///     }
/// }
#[macro_export]
macro_rules! clone {
    ($($(@ $strength:ident)? $variables:ident),+ => @default-panic, move || $body:block ) => (
        {
            $( $crate::to_type_before!($(@ $strength)? $variables); )*
            move || {
                $( $crate::to_type_after!(@default-panic, $(@ $strength)? $variables );)*
                $body
            }
        }
    );
    ($($(@ $strength:ident)? $variables:ident),+ => $(@default-return $return_value:expr,)? move || $body:block ) => (
        {
            $( $crate::to_type_before!($(@ $strength)? $variables); )*
            move || {
                let return_value = || $crate::to_return_value!($($return_value)?);
                $( $crate::to_type_after!($(@ $strength)? $variables, return_value );)*
                $body
            }
        }
    );
    ($($(@ $strength:ident)? $variables:ident),+ => @default-panic, move | $($pattern:pat),* | $body:block ) => (
        {
            $( $crate::to_type_before!($(@ $strength)? $variables); )*
            move |$($pattern),*| {
                $( $crate::to_type_after!(@default-panic, $(@ $strength)? $variables );)*
                $body
            }
        }
    );
    ($($(@ $strength:ident)? $variables:ident),+ => $(@default-return $return_value:expr,)? move | $($pattern:pat),* | $body:block ) => (
        {
            $( $crate::to_type_before!($(@ $strength)? $variables); )*
            move |$($pattern),*| {
                let return_value = || $crate::to_return_value!($($return_value)?);
                $( $crate::to_type_after!($(@ $strength)? $variables, return_value );)*
                $body
            }
        }
    );
}
<|endoftext|>


<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use anyhow::{anyhow, bail, Result};
use move_binary_format::{
    layout::{ModuleCache, TypeLayoutBuilder},
    normalized::{Function, Type},
    CompiledModule,
};
use move_core_types::{
    account_address::AccountAddress,
    identifier::IdentStr,
    language_storage::{ModuleId, ResourceKey, TypeTag},
    resolver::MoveResolver,
    value::MoveValue,
};
use read_write_set_types::{Access, AccessPath, Offset, ReadWriteSet, RootAddress};
use std::{
    fmt::{self, Formatter},
    ops::Deref,
};

/// A read/write set state with no unbound formals or type variables
#[derive(Debug)]
pub struct ConcretizedFormals(ReadWriteSet);

/// A read/write set state with no secondary indexes and no unbound formals or type variables
#[derive(Debug)]
pub struct ConcretizedSecondaryIndexes(ConcretizedFormals);

impl ConcretizedFormals {
    /// Return the `ResourceKey`'s that may be written by `self`.
    /// For example: if `self` is 0x7/0x1::AModule::AResource/f/g -> ReadWrite, this will return
    /// 0x7/0x1::AModule.
    pub fn get_keys_written(&self) -> Option<Vec<ResourceKey>> {
        self.0.get_keys_written()
    }

    /// Return the `ResourceKey`'s read by `self`.
    pub fn get_keys_read(&self) -> Option<Vec<ResourceKey>> {
        self.0.get_keys_read()
    }

    /// Concretize all secondary indexes in `self` using `blockchain_view` and return the result. For
    /// example: if `self` is 0x7/0x1::AModule::AResource/addr_field/0x2::M2::R/f -> Write and the
    /// value of 0x7/0x1::AModule::AResource/addr_field is 0xA in `blockchain_view`, this will
    /// return { 0x7/0x1::AModule::AResource/addr_field -> Read, 0xA/0x2::M2::R/f -> Write }
    fn concretize_secondary_indexes<R: MoveResolver>(
        self,
        blockchain_view: &R,
    ) -> Option<ConcretizedSecondaryIndexes> {
        // TODO: check if there are no secondary indexes and return accesses if so
        let mut acc = ReadWriteSet::new();
        let module_cache = ModuleCache::new(blockchain_view);
        self.0.iter_paths(|access_path, access| {
            Self::concretize_secondary_indexes_(
                &module_cache,
                blockchain_view,
                access_path,
                access,
                &mut acc,
            )
            .ok()
        })?;
        Some(ConcretizedSecondaryIndexes(ConcretizedFormals(acc)))
    }

    /// Construct a `ConcretizedFormals` from `accesses` by binding the formals and type variables in
    /// `accesses` to `actuals` and `type_actuals`.
    fn from_args_(
        read_write_set: &ReadWriteSet,
        actuals: &[Option<AccountAddress>],
        type_actuals: &[TypeTag],
    ) -> ConcretizedFormals {
        ConcretizedFormals(read_write_set.sub_actuals(actuals, type_actuals))
    }

    /// Construct a `ConcretizedFormals` from `accesses` by binding the formals and type variables in
    /// `accesses` to `signers`/`actuals` and `type_actuals`.
    /// For example: if `accesses` is Formal(0)/0x1::M::S<TypeVar(0)>/f -> Read, `signers` is 0xA
    /// and type_actuals is 0x2::M2::S2, this will return  0xA/0x1::M::S<0x2::M2::S@>/f -> Read
    pub fn from_args(
        read_write_set: &ReadWriteSet,
        signers: &[AccountAddress],
        actuals: &[Vec<u8>],
        formal_types: &[TypeTag],
        type_actuals: &[TypeTag],
    ) -> Result<ConcretizedFormals> {
        let mut new_actuals = signers
            .iter()
            .map(|addr| Some(*addr))
            .collect::<Vec<Option<_>>>();
        assert_eq!(
            formal_types.len(),
            actuals.len() + signers.len(),
            "Formal/actual arity mismatch"
        );
        // Deserialize the address actuals, use an None for the rest
        let num_signers = signers.len();
        // formal_types includes all formal types (including signers), but actuals is only
        // the non-signer actuals.
        for (actual_index, ty) in formal_types[num_signers..].iter().enumerate() {
            let actual = if let TypeTag::Address = ty {
                Some(AccountAddress::from_bytes(&actuals[actual_index])?)
            } else {
                None
            };
            new_actuals.push(actual);
        }
        Ok(Self::from_args_(
            read_write_set,
            new_actuals.as_slice(),
            type_actuals,
        ))
    }

    /// Concretize the secondary in `offsets` -> `access` using `annotator` and add the results to
    /// `acc`.
    fn concretize_offsets<R: MoveResolver>(
        module_cache: &ModuleCache<&R>,
        blockchain_view: &R,
        access_path: AccessPath,
        mut next_value: MoveValue,
        next_offset_index: usize,
        access: &Access,
        acc: &mut ReadWriteSet,
    ) -> Result<()> {
        let offsets = access_path.offset();
        for next_offset_index in next_offset_index..offsets.len() {
            let next_offset = &offsets[next_offset_index];
            match next_offset {
                Offset::Field(index) => {
                    if let MoveValue::Struct(s) = next_value {
                        let fields = s.fields();
                        next_value = fields[*index].clone();
                    } else {
                        bail!("Malformed access path {:?}; expected struct value as prefix to field offset {:?}, but got {:?}",
                               access_path, next_offset, next_value)
                    }
                }
                Offset::Global(g_offset) => {
                    // secondary index. previous offset should have been an address value
                    if let MoveValue::Address(a) = next_value {
                        let mut new_ap = AccessPath::new_global_constant(a, g_offset.clone());
                        for o in offsets[next_offset_index + 1..].iter() {
                            new_ap.add_offset(o.clone())
                        }
                        return Self::concretize_secondary_indexes_(
                            module_cache,
                            blockchain_view,
                            &new_ap,
                            access,
                            acc,
                        );
                    } else {
                        bail!(
                            "Malformed access path {:?}: expected address value before Global offset, but found {:?}",
                            access_path,
                            next_value
                        );
                    }
                }
                Offset::VectorIndex => {
                    if let MoveValue::Vector(v_contents) = &next_value {
                        // concretize offsets for each element in the vector
                        for val in v_contents {
                            Self::concretize_offsets(
                                module_cache,
                                blockchain_view,
                                access_path.clone(),
                                val.clone(),
                                next_offset_index + 1,
                                access,
                                acc,
                            )?;
                        }
                        return Ok(());
                    } else {
                        bail!(
                            "Malformed access path {:?}: expected vector value before VectorIndex offset, but found {:?}",
                            access_path,
                            next_value
                        );
                    }
                }
            }
        }
        // Got to the end of the concrete access path. Add it to the accumulator
        acc.add_access_path(access_path, *access);

        Ok(())
    }

    /// Concretize the secondary indexes in `access_path` and add the result to `acc`. For example
    fn concretize_secondary_indexes_<R: MoveResolver>(
        module_cache: &ModuleCache<&R>,
        blockchain_view: &R,
        access_path: &AccessPath,
        access: &Access,
        acc: &mut ReadWriteSet,
    ) -> Result<()> {
        if let RootAddress::Const(g) = &access_path.root.root {
            let tag = access_path
                .root
                .type_
                .clone()
                .into_struct_tag()
                .ok_or_else(|| {
                    anyhow!("Unbound type variable found: {:?}", access_path.root.type_)
                })?;
            if let Some(resource_bytes) = blockchain_view
                .get_resource(g, &tag)
                .map_err(|_| anyhow!("Failed to get resource for {:?}::{:?}", g, tag))?
            {
                let layout = TypeLayoutBuilder::build_runtime(&TypeTag::Struct(tag), module_cache)
                    .map_err(|_| anyhow!("Failed to resolve type: {:?}", access_path.root.type_))?;

                let resource =
                    MoveValue::simple_deserialize(&resource_bytes, &layout).map_err(|_| {
                        anyhow!(
                            "Failed to deserialize move value of type: {:?}",
                            access_path.root.type_
                        )
                    })?;
                Self::concretize_offsets(
                    module_cache,
                    blockchain_view,
                    access_path.clone(),
                    resource,
                    0,
                    access,
                    acc,
                )?;
            } // else, resource not present. this can happen/is expected because the R/W set is overapproximate
        }
        Ok(())
    }
}

/// Bind all formals and type variables in `accesses` using `signers`, `actuals`, and
/// `type_actuals`. In addition, concretize all secondary indexes in `accesses` against the state in
/// `blockchain_view`.
pub fn concretize(
    accesses: &ReadWriteSet,
    module: &ModuleId,
    fun: &IdentStr,
    signers: &[AccountAddress],
    actuals: &[Vec<u8>],
    type_actuals: &[TypeTag],
    blockchain_view: &impl MoveResolver,
) -> Result<ConcretizedSecondaryIndexes> {
    let subst_map = type_actuals
        .iter()
        .map(|ty| Type::from(ty.clone()))
        .collect::<Vec<_>>();

    let compiled_module = CompiledModule::deserialize(
        &blockchain_view
            .get_module(module)
            .map_err(|_| anyhow!("Failed to get module from storage"))?
            .ok_or_else(|| anyhow!("Failed to get module"))?,
    )
    .map_err(|_| anyhow!("Failed to deserialize module"))?;

    let func_type = Function::new_from_name(&compiled_module, fun)
        .ok_or_else(|| anyhow!("Failed to find function"))?
        .parameters
        .iter()
        .map(|ty| ty.subst(&subst_map).into_type_tag())
        .collect::<Option<Vec<_>>>()
        .ok_or_else(|| anyhow!("Failed to substitute types"))?;
    let concretized_formals = ConcretizedFormals::from_args(
        accesses,
        signers,
        actuals,
        func_type.as_slice(),
        type_actuals,
    )?;

    concretized_formals
        .concretize_secondary_indexes(blockchain_view)
        .ok_or_else(|| anyhow!("Failed to concretize secondary index"))
}

impl Deref for ConcretizedFormals {
    type Target = ReadWriteSet;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl Deref for ConcretizedSecondaryIndexes {
    type Target = ConcretizedFormals;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl fmt::Display for ConcretizedFormals {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        writeln!(f, "{}", self.0)
    }
}

impl fmt::Display for ConcretizedSecondaryIndexes {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        writeln!(f, "{}", self.0)
    }
}
<commit_msg>[read-write-set] Skip secondary index concretization.<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use anyhow::{anyhow, bail, Result};
use move_binary_format::{
    layout::{ModuleCache, TypeLayoutBuilder},
    normalized::{Function, Type},
    CompiledModule,
};
use move_core_types::{
    account_address::AccountAddress,
    identifier::IdentStr,
    language_storage::{ModuleId, ResourceKey, TypeTag},
    resolver::MoveResolver,
    value::MoveValue,
};
use read_write_set_types::{Access, AccessPath, Offset, ReadWriteSet, RootAddress};
use std::{
    fmt::{self, Formatter},
    ops::Deref,
};

/// A read/write set state with no unbound formals or type variables
#[derive(Debug)]
pub struct ConcretizedFormals(ReadWriteSet);

/// A read/write set state with no secondary indexes and no unbound formals or type variables
#[derive(Debug)]
pub struct ConcretizedSecondaryIndexes(ConcretizedFormals);

impl ConcretizedFormals {
    /// Return the `ResourceKey`'s that may be written by `self`.
    /// For example: if `self` is 0x7/0x1::AModule::AResource/f/g -> ReadWrite, this will return
    /// 0x7/0x1::AModule.
    pub fn get_keys_written(&self) -> Option<Vec<ResourceKey>> {
        self.0.get_keys_written()
    }

    /// Return the `ResourceKey`'s read by `self`.
    pub fn get_keys_read(&self) -> Option<Vec<ResourceKey>> {
        self.0.get_keys_read()
    }

    /// Concretize all secondary indexes in `self` using `blockchain_view` and return the result. For
    /// example: if `self` is 0x7/0x1::AModule::AResource/addr_field/0x2::M2::R/f -> Write and the
    /// value of 0x7/0x1::AModule::AResource/addr_field is 0xA in `blockchain_view`, this will
    /// return { 0x7/0x1::AModule::AResource/addr_field -> Read, 0xA/0x2::M2::R/f -> Write }
    fn concretize_secondary_indexes<R: MoveResolver>(
        self,
        blockchain_view: &R,
    ) -> Option<ConcretizedSecondaryIndexes> {
        // TODO: check if there are no secondary indexes and return accesses if so
        let mut acc = ReadWriteSet::new();
        let module_cache = ModuleCache::new(blockchain_view);
        self.0.iter_paths(|access_path, access| {
            Self::concretize_secondary_indexes_(
                &module_cache,
                blockchain_view,
                access_path,
                access,
                &mut acc,
            )
            .ok()
        })?;
        Some(ConcretizedSecondaryIndexes(ConcretizedFormals(acc)))
    }

    /// Construct a `ConcretizedFormals` from `accesses` by binding the formals and type variables in
    /// `accesses` to `actuals` and `type_actuals`.
    fn from_args_(
        read_write_set: &ReadWriteSet,
        actuals: &[Option<AccountAddress>],
        type_actuals: &[TypeTag],
    ) -> ConcretizedFormals {
        ConcretizedFormals(read_write_set.sub_actuals(actuals, type_actuals))
    }

    /// Construct a `ConcretizedFormals` from `accesses` by binding the formals and type variables in
    /// `accesses` to `signers`/`actuals` and `type_actuals`.
    /// For example: if `accesses` is Formal(0)/0x1::M::S<TypeVar(0)>/f -> Read, `signers` is 0xA
    /// and type_actuals is 0x2::M2::S2, this will return  0xA/0x1::M::S<0x2::M2::S@>/f -> Read
    pub fn from_args(
        read_write_set: &ReadWriteSet,
        signers: &[AccountAddress],
        actuals: &[Vec<u8>],
        formal_types: &[TypeTag],
        type_actuals: &[TypeTag],
    ) -> Result<ConcretizedFormals> {
        let mut new_actuals = signers
            .iter()
            .map(|addr| Some(*addr))
            .collect::<Vec<Option<_>>>();
        assert_eq!(
            formal_types.len(),
            actuals.len() + signers.len(),
            "Formal/actual arity mismatch"
        );
        // Deserialize the address actuals, use an None for the rest
        let num_signers = signers.len();
        // formal_types includes all formal types (including signers), but actuals is only
        // the non-signer actuals.
        for (actual_index, ty) in formal_types[num_signers..].iter().enumerate() {
            let actual = if let TypeTag::Address = ty {
                Some(AccountAddress::from_bytes(&actuals[actual_index])?)
            } else {
                None
            };
            new_actuals.push(actual);
        }
        Ok(Self::from_args_(
            read_write_set,
            new_actuals.as_slice(),
            type_actuals,
        ))
    }

    /// Concretize the secondary in `offsets` -> `access` using `annotator` and add the results to
    /// `acc`.
    fn concretize_offsets<R: MoveResolver>(
        module_cache: &ModuleCache<&R>,
        blockchain_view: &R,
        access_path: AccessPath,
        mut next_value: MoveValue,
        next_offset_index: usize,
        access: &Access,
        acc: &mut ReadWriteSet,
    ) -> Result<()> {
        let offsets = access_path.offset();
        for next_offset_index in next_offset_index..offsets.len() {
            let next_offset = &offsets[next_offset_index];
            match next_offset {
                Offset::Field(index) => {
                    if let MoveValue::Struct(s) = next_value {
                        let fields = s.fields();
                        next_value = fields[*index].clone();
                    } else {
                        bail!("Malformed access path {:?}; expected struct value as prefix to field offset {:?}, but got {:?}",
                               access_path, next_offset, next_value)
                    }
                }
                Offset::Global(g_offset) => {
                    // secondary index. previous offset should have been an address value
                    if let MoveValue::Address(a) = next_value {
                        let mut new_ap = AccessPath::new_global_constant(a, g_offset.clone());
                        for o in offsets[next_offset_index + 1..].iter() {
                            new_ap.add_offset(o.clone())
                        }
                        return Self::concretize_secondary_indexes_(
                            module_cache,
                            blockchain_view,
                            &new_ap,
                            access,
                            acc,
                        );
                    } else {
                        bail!(
                            "Malformed access path {:?}: expected address value before Global offset, but found {:?}",
                            access_path,
                            next_value
                        );
                    }
                }
                Offset::VectorIndex => {
                    if let MoveValue::Vector(v_contents) = &next_value {
                        // concretize offsets for each element in the vector
                        for val in v_contents {
                            Self::concretize_offsets(
                                module_cache,
                                blockchain_view,
                                access_path.clone(),
                                val.clone(),
                                next_offset_index + 1,
                                access,
                                acc,
                            )?;
                        }
                        return Ok(());
                    } else {
                        bail!(
                            "Malformed access path {:?}: expected vector value before VectorIndex offset, but found {:?}",
                            access_path,
                            next_value
                        );
                    }
                }
            }
        }
        // Got to the end of the concrete access path. Add it to the accumulator
        acc.add_access_path(access_path, *access);

        Ok(())
    }

    /// Concretize the secondary indexes in `access_path` and add the result to `acc`. For example
    fn concretize_secondary_indexes_<R: MoveResolver>(
        module_cache: &ModuleCache<&R>,
        blockchain_view: &R,
        access_path: &AccessPath,
        access: &Access,
        acc: &mut ReadWriteSet,
    ) -> Result<()> {
        if let RootAddress::Const(g) = &access_path.root.root {
            let tag = access_path
                .root
                .type_
                .clone()
                .into_struct_tag()
                .ok_or_else(|| {
                    anyhow!("Unbound type variable found: {:?}", access_path.root.type_)
                })?;
            if let Some(resource_bytes) = blockchain_view
                .get_resource(g, &tag)
                .map_err(|_| anyhow!("Failed to get resource for {:?}::{:?}", g, tag))?
            {
                let layout = TypeLayoutBuilder::build_runtime(&TypeTag::Struct(tag), module_cache)
                    .map_err(|_| anyhow!("Failed to resolve type: {:?}", access_path.root.type_))?;

                let resource =
                    MoveValue::simple_deserialize(&resource_bytes, &layout).map_err(|_| {
                        anyhow!(
                            "Failed to deserialize move value of type: {:?}",
                            access_path.root.type_
                        )
                    })?;
                Self::concretize_offsets(
                    module_cache,
                    blockchain_view,
                    access_path.clone(),
                    resource,
                    0,
                    access,
                    acc,
                )?;
            } // else, resource not present. this can happen/is expected because the R/W set is overapproximate
        }
        Ok(())
    }
}

/// Bind all formals and type variables in `accesses` using `signers`, `actuals`, and
/// `type_actuals`.
pub fn bind_formals(
    accesses: &ReadWriteSet,
    module: &ModuleId,
    fun: &IdentStr,
    signers: &[AccountAddress],
    actuals: &[Vec<u8>],
    type_actuals: &[TypeTag],
    blockchain_view: &impl MoveResolver,
) -> Result<ConcretizedFormals> {
    let subst_map = type_actuals
        .iter()
        .map(|ty| Type::from(ty.clone()))
        .collect::<Vec<_>>();

    let compiled_module = CompiledModule::deserialize(
        &blockchain_view
            .get_module(module)
            .map_err(|_| anyhow!("Failed to get module from storage"))?
            .ok_or_else(|| anyhow!("Failed to get module"))?,
    )
    .map_err(|_| anyhow!("Failed to deserialize module"))?;

    let func_type = Function::new_from_name(&compiled_module, fun)
        .ok_or_else(|| anyhow!("Failed to find function"))?
        .parameters
        .iter()
        .map(|ty| ty.subst(&subst_map).into_type_tag())
        .collect::<Option<Vec<_>>>()
        .ok_or_else(|| anyhow!("Failed to substitute types"))?;
    ConcretizedFormals::from_args(
        accesses,
        signers,
        actuals,
        func_type.as_slice(),
        type_actuals,
    )
}

/// Bind all formals and type variables in `accesses` using `signers`, `actuals`, and
/// `type_actuals`. In addition, concretize all secondary indexes in `accesses` against the state in
/// `blockchain_view`.
pub fn concretize(
    accesses: &ReadWriteSet,
    module: &ModuleId,
    fun: &IdentStr,
    signers: &[AccountAddress],
    actuals: &[Vec<u8>],
    type_actuals: &[TypeTag],
    blockchain_view: &impl MoveResolver,
) -> Result<ConcretizedSecondaryIndexes> {
    bind_formals(
        accesses,
        module,
        fun,
        signers,
        actuals,
        type_actuals,
        blockchain_view,
    )?
    .concretize_secondary_indexes(blockchain_view)
    .ok_or_else(|| anyhow!("Failed to concretize secondary index"))
}

impl Deref for ConcretizedFormals {
    type Target = ReadWriteSet;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl Deref for ConcretizedSecondaryIndexes {
    type Target = ConcretizedFormals;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl fmt::Display for ConcretizedFormals {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        writeln!(f, "{}", self.0)
    }
}

impl fmt::Display for ConcretizedSecondaryIndexes {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        writeln!(f, "{}", self.0)
    }
}
<|endoftext|>


<commit_before>pub fn decode(ch:char) -> Option<u8> {
  match ch {
    '0' => Some(0),
    '1' => Some(1),
    '2' => Some(2),
    '3' => Some(3),
    '4' => Some(4),
    '5' => Some(5),
    '6' => Some(6),
    '7' => Some(7),
    '8' => Some(8),
    '9' => Some(9),

    'b' => Some(10),
    'c' => Some(11),
    'd' => Some(12),
    'e' => Some(13),
    'f' => Some(14),
    'g' => Some(15),
    'h' => Some(16),
    'j' => Some(17),
    'k' => Some(18),
    'm' => Some(19),
    'n' => Some(20),
    'p' => Some(21),
    'q' => Some(22),
    'r' => Some(23),
    's' => Some(24),
    't' => Some(25),
    'u' => Some(26),
    'v' => Some(27),
    'w' => Some(28),
    'x' => Some(29),
    'y' => Some(30),
    'z' => Some(31),
    _   => None
  }
}<commit_msg>Adds geohash::base32::encode<commit_after>pub fn decode(ch:char) -> Option<u8> {
  match ch {
    '0' => Some(0),
    '1' => Some(1),
    '2' => Some(2),
    '3' => Some(3),
    '4' => Some(4),
    '5' => Some(5),
    '6' => Some(6),
    '7' => Some(7),
    '8' => Some(8),
    '9' => Some(9),

    'b' => Some(10),
    'c' => Some(11),
    'd' => Some(12),
    'e' => Some(13),
    'f' => Some(14),
    'g' => Some(15),
    'h' => Some(16),
    'j' => Some(17),
    'k' => Some(18),
    'm' => Some(19),
    'n' => Some(20),
    'p' => Some(21),
    'q' => Some(22),
    'r' => Some(23),
    's' => Some(24),
    't' => Some(25),
    'u' => Some(26),
    'v' => Some(27),
    'w' => Some(28),
    'x' => Some(29),
    'y' => Some(30),
    'z' => Some(31),
    _   => None
  }
}

pub fn encode(in:u8) -> Option<char> {
  match in {
    0   => Some('0'),
    1   => Some('1'),
    2   => Some('2'),
    3   => Some('3'),
    4   => Some('4'),
    5   => Some('5'),
    6   => Some('6'),
    7   => Some('7'),
    8   => Some('8'),
    9   => Some('9'),
    10  => Some('b'),
    11  => Some('c'),
    12  => Some('d'),
    13  => Some('e'),
    14  => Some('f'),
    15  => Some('g'),
    16  => Some('h'),
    17  => Some('j'),
    18  => Some('k'),
    19  => Some('m'),
    20  => Some('n'),
    21  => Some('p'),
    22  => Some('q'),
    23  => Some('r'),
    24  => Some('s'),
    25  => Some('t'),
    26  => Some('u'),
    27  => Some('v'),
    28  => Some('w'),
    29  => Some('x'),
    30  => Some('y'),
    31  => Some('z'),
    _   => None
  }
}

<|endoftext|>


<commit_before>//! C API extensions to experiment with eager execution of kernels.
//!
//! WARNING: The underlying C-API for the eager execution is not guaranteed to be
//! stable and can be changed without notice, which could result in breaking.

mod context;
pub use context::*;

mod tensor_handle;
pub use tensor_handle::*;

mod op;

pub use op::raw_ops;
<commit_msg>add ToTensorHandle helper trait<commit_after>//! C API extensions to experiment with eager execution of kernels.
//!
//! WARNING: The underlying C-API for the eager execution is not guaranteed to be
//! stable and can be changed without notice, which could result in breaking.

mod context;
pub use context::*;

mod tensor_handle;
pub use tensor_handle::*;

mod op;

pub use op::raw_ops;

use crate::{Result, Tensor, TensorType};

/// Simple helper trait to convert a Tensor into a TensorHandle for use in eager
/// execution.
pub trait ToTensorHandle<'a> {
    /// Convert the Tensor or TensorHandle into a new TensorHandle.
    ///
    /// _Warning_ : This function may create multiple handles to the same
    /// underlying tensor. Users should be careful not to modify the tensor
    /// after converting it to a handle. Also, users should be careful not
    /// to modify the tensor obtained via the TensorHandle's `resolve` method.
    fn to_handle(&self, ctx: &'a Context) -> Result<TensorHandle<'a>>;
}

impl<'a, T> ToTensorHandle<'a> for Tensor<T>
where
    T: TensorType,
{
    fn to_handle(&self, ctx: &'a Context) -> Result<TensorHandle<'a>> {
        TensorHandle::new(ctx, self)
    }
}

impl<'a> ToTensorHandle<'a> for TensorHandle<'a> {
    fn to_handle(&self, _: &'a Context) -> Result<TensorHandle<'a>> {
        self.copy_sharing_tensor()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::eager::{Context, ContextOptions};
    use crate::Tensor;

    #[test]
    fn tensor_to_handle() {
        let ctx = Context::new(ContextOptions::new()).unwrap();
        let tensor = Tensor::<i32>::new(&[1, 2, 3, 4]);
        let handle = tensor.to_handle(&ctx).unwrap();
        assert_eq!(handle.num_dims().unwrap(), 4);
        assert_eq!(handle.dim(0).unwrap(), 1);
        assert_eq!(handle.dim(1).unwrap(), 2);
        assert_eq!(handle.dim(2).unwrap(), 3);
        assert_eq!(handle.dim(3).unwrap(), 4);

        let tensor = Tensor::<i32>::new(&[1, 2, 3, 4]);
        let handle = &tensor.to_handle(&ctx).unwrap();
        assert_eq!(handle.num_dims().unwrap(), 4);
        assert_eq!(handle.dim(0).unwrap(), 1);
        assert_eq!(handle.dim(1).unwrap(), 2);
        assert_eq!(handle.dim(2).unwrap(), 3);
        assert_eq!(handle.dim(3).unwrap(), 4);
    }

    #[test]
    fn handle_to_handle() {
        let ctx = Context::new(ContextOptions::new()).unwrap();
        let tensor = Tensor::<i32>::new(&[1, 2, 3, 4]);
        let handle = tensor.to_handle(&ctx).unwrap();
        let handle2 = handle.to_handle(&ctx).unwrap();
        let tensor2: Tensor<i32> = handle2.resolve().unwrap();
        assert_eq!(&tensor[..], &tensor2[..]);
    }
}
<|endoftext|>