<commit_before>use super::CharIndex;

lazy_static! {
    static ref BIGRAMS: Vec<f64> = {
        let f = include_str!("data/bigrams.txt");
        let mut bigrams = vec![0.0; 676];  // 26^2 = 676

        for line in f.lines() {
            let line: Vec<_> = line.split(' ').collect();
            let bigram: &str = line[0];
            let count: f64 = line[1].parse().unwrap();

            let index = bigram.chars().fold(0, |acc, c| 26 * acc + c.index());
            bigrams[index] = count.ln();
        }

        bigrams
    };

    static ref TRIGRAMS: Vec<f64> = {
        let f = include_str!("data/trigrams.txt");
        let mut trigrams = vec![0.0; 17_576];  // 26^3 = 17,576

        for line in f.lines() {
            let line: Vec<_> = line.split(' ').collect();
            let trigram: &str = line[0];
            let count: f64 = line[1].parse().unwrap();

            let index = trigram.chars().fold(0, |acc, c| 26 * acc + c.index());
            trigrams[index] = count.ln();
        }

        trigrams
    };

    static ref QUADGRAMS: Vec<f64> = {
        let f = include_str!("data/quadgrams.txt");
        let mut quadgrams = vec![0.0; 456_976];  // 26^4 = 456,976

        for line in f.lines() {
            let line: Vec<_> = line.split(' ').collect();
            let quadgram: &str = line[0];
            let count: f64 = line[1].parse().unwrap();

            let index = quadgram.chars().fold(0, |acc, c| 26 * acc + c.index());
            quadgrams[index] = count.ln();
        }

        quadgrams
    };
}

/// For a given `n` and `ngram` vector, returns the sum of log-probabilities
/// for each n-gram substring.
fn ngram_score(n: usize, ngrams: &Vec<f64>, msg: &str) -> f64 {
    let char_indices: Vec<usize> = msg.chars()
        .filter(|&c| c.is_alphabetic())
        .map(|c| c.index())
        .collect();

    if char_indices.len() < n {
        panic!("Message has fewer than n alphabetic characters.");
    }

    char_indices.windows(n)
        .map(|w| w.iter().fold(0, |acc, x| 26 * acc + x))
        .map(|i| ngrams[i])
        .sum()
}

pub trait FitnessFn {
    /// Returns the fitness score for a given message after stripping away
    /// non-alphabetic characters.
    fn score(msg: &str) -> f64;
}

/// Bigram probability fitness function for English.
pub struct Bigram;
impl FitnessFn for Bigram {
    fn score(msg: &str) -> f64 {
        ngram_score(2, &BIGRAMS, msg)
    }
}

/// Trigram probability fitness function for English.
pub struct Trigram;
impl FitnessFn for Trigram {
    fn score(msg: &str) -> f64 {
        ngram_score(3, &TRIGRAMS, msg)
    }
}

/// Quadgram probability fitness function for English.
pub struct Quadgram;
impl FitnessFn for Quadgram {
    fn score(msg: &str) -> f64 {
        ngram_score(4, &QUADGRAMS, msg)
    }
}

/// Returns the index of coincidence for the given message.
pub struct IoC;
impl FitnessFn for IoC {
    fn score(msg: &str) -> f64 {
        let char_indices: Vec<usize> = msg.chars()
            .filter(|&c| c.is_alphabetic())
            .map(|c| c.index())
            .collect();

        let mut buckets = [0; 26];

        for c in &char_indices {
            buckets[*c] += 1;
        }

        let tot: isize = buckets
            .iter()
            .map(|n| n * (n - 1))
            .sum();

        let n = char_indices.len();
        return tot as f64 / (n * (n - 1) / 26) as f64;
    }
}

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

    macro_rules! assert_approx_eq {
        ($a:expr, $b:expr) => {
            let (a, b) = (&$a, &$b);
            assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b);
        }
    }

    #[test]
    fn quadgram_estimates() {
        assert_approx_eq!(QUADGRAMS[0], 8.81060879);
        assert_approx_eq!(Quadgram::score("THE QUICK BROWN FOX"), 149.80102862);
    }

    #[test]
    fn sensible_ngram_scores() {
        assert!(Bigram::score("AN ENGLISH PHRASE") > Bigram::score("ESARHP HSILGNE NA"));
        assert!(Trigram::score("AN ENGLISH PHRASE") > Trigram::score("ESARHP HSILGNE NA"));
        assert!(Quadgram::score("AN ENGLISH PHRASE") > Quadgram::score("ESARHP HSILGNE NA"));
    }

    #[test]
    #[should_panic]
    fn invalid_qgram_check() {
        Quadgram::score("ABC");
    }

    #[test]
    fn sensible_ioc_scores() {
        assert_approx_eq!(IoC::score("THE INDEX OF COINCIDENCE PROVIDES A MEASURE OF HOW LIKELY IT IS TO DRAW TWO MATCHING LETTERS BY RANDOMLY SELECTING TWO LETTERS FROM A GIVEN TEXT"), 1.55925925);

        assert_approx_eq!(IoC::score(&"ABCDEFGHIJKLMNOPQRSTUVWXYZ".repeat(100)), 0.99038091);
    }
}
<commit_msg>Fix bug with lowercase characters in decryption<commit_after>use super::CharIndex;

lazy_static! {
    static ref BIGRAMS: Vec<f64> = {
        let f = include_str!("data/bigrams.txt");
        let mut bigrams = vec![0.0; 676];  // 26^2 = 676

        for line in f.lines() {
            let line: Vec<_> = line.split(' ').collect();
            let bigram: &str = line[0];
            let count: f64 = line[1].parse().unwrap();

            let index = bigram.chars().fold(0, |acc, c| 26 * acc + c.index());
            bigrams[index] = count.ln();
        }

        bigrams
    };

    static ref TRIGRAMS: Vec<f64> = {
        let f = include_str!("data/trigrams.txt");
        let mut trigrams = vec![0.0; 17_576];  // 26^3 = 17,576

        for line in f.lines() {
            let line: Vec<_> = line.split(' ').collect();
            let trigram: &str = line[0];
            let count: f64 = line[1].parse().unwrap();

            let index = trigram.chars().fold(0, |acc, c| 26 * acc + c.index());
            trigrams[index] = count.ln();
        }

        trigrams
    };

    static ref QUADGRAMS: Vec<f64> = {
        let f = include_str!("data/quadgrams.txt");
        let mut quadgrams = vec![0.0; 456_976];  // 26^4 = 456,976

        for line in f.lines() {
            let line: Vec<_> = line.split(' ').collect();
            let quadgram: &str = line[0];
            let count: f64 = line[1].parse().unwrap();

            let index = quadgram.chars().fold(0, |acc, c| 26 * acc + c.index());
            quadgrams[index] = count.ln();
        }

        quadgrams
    };
}

/// For a given `n` and `ngram` vector, returns the sum of log-probabilities
/// for each n-gram substring.
fn ngram_score(n: usize, ngrams: &Vec<f64>, msg: &str) -> f64 {
    let char_indices: Vec<usize> = msg.to_uppercase().chars()
        .filter(|&c| c.is_alphabetic())
        .map(|c| c.index())
        .collect();

    if char_indices.len() < n {
        panic!("Message has fewer than n alphabetic characters.");
    }

    char_indices.windows(n)
        .map(|w| w.iter().fold(0, |acc, x| 26 * acc + x))
        .map(|i| ngrams[i])
        .sum()
}

pub trait FitnessFn {
    /// Returns the fitness score for a given message after stripping away
    /// non-alphabetic characters.
    fn score(msg: &str) -> f64;
}

/// Bigram probability fitness function for English.
pub struct Bigram;
impl FitnessFn for Bigram {
    fn score(msg: &str) -> f64 {
        ngram_score(2, &BIGRAMS, msg)
    }
}

/// Trigram probability fitness function for English.
pub struct Trigram;
impl FitnessFn for Trigram {
    fn score(msg: &str) -> f64 {
        ngram_score(3, &TRIGRAMS, msg)
    }
}

/// Quadgram probability fitness function for English.
pub struct Quadgram;
impl FitnessFn for Quadgram {
    fn score(msg: &str) -> f64 {
        ngram_score(4, &QUADGRAMS, msg)
    }
}

/// Returns the index of coincidence for the given message.
pub struct IoC;
impl FitnessFn for IoC {
    fn score(msg: &str) -> f64 {
        let char_indices: Vec<usize> = msg.chars()
            .filter(|&c| c.is_alphabetic())
            .map(|c| c.index())
            .collect();

        let mut buckets = [0; 26];

        for c in &char_indices {
            buckets[*c] += 1;
        }

        let tot: isize = buckets
            .iter()
            .map(|n| n * (n - 1))
            .sum();

        let n = char_indices.len();
        return tot as f64 / (n * (n - 1) / 26) as f64;
    }
}

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

    macro_rules! assert_approx_eq {
        ($a:expr, $b:expr) => {
            let (a, b) = (&$a, &$b);
            assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b);
        }
    }

    #[test]
    fn quadgram_estimates() {
        assert_approx_eq!(QUADGRAMS[0], 8.81060879);
        assert_approx_eq!(Quadgram::score("THE QUICK BROWN FOX"), 149.80102862);
    }

    #[test]
    fn sensible_ngram_scores() {
        assert!(Bigram::score("AN ENGLISH PHRASE") > Bigram::score("ESARHP HSILGNE NA"));
        assert!(Trigram::score("AN ENGLISH PHRASE") > Trigram::score("ESARHP HSILGNE NA"));
        assert!(Quadgram::score("AN ENGLISH PHRASE") > Quadgram::score("ESARHP HSILGNE NA"));
    }

    #[test]
    #[should_panic]
    fn invalid_qgram_check() {
        Quadgram::score("ABC");
    }

    #[test]
    fn sensible_ioc_scores() {
        assert_approx_eq!(IoC::score("THE INDEX OF COINCIDENCE PROVIDES A MEASURE OF HOW LIKELY IT IS TO DRAW TWO MATCHING LETTERS BY RANDOMLY SELECTING TWO LETTERS FROM A GIVEN TEXT"), 1.55925925);

        assert_approx_eq!(IoC::score(&"ABCDEFGHIJKLMNOPQRSTUVWXYZ".repeat(100)), 0.99038091);
    }
}
<|endoftext|>


<commit_before>use std::iter::repeat;
use std::ops::{Index, RangeFull};
use std::fmt::Debug;

use super::point::Point;
use super::number::NumberOps;

#[derive(Debug)]
pub struct Ring<T> {
   v: Vec<T>,
   start: usize,
   end: usize,
}

impl<T> Ring<T> where T: Default + Clone + Debug {
   #[inline]
   pub fn new(capacity: usize) -> Self {
      let v = repeat(T::default()).take(capacity).collect();

      Ring { v: v, start: 0, end: 0 }
   }

   #[inline]
   pub fn len(&self) -> usize {
      self.end - self.start
   }

   #[inline]
   pub fn last(&self) -> Option<&T> {
      if self.start == self.end {
         None
      } else {
         Some(unsafe {
            self.v.get_unchecked(self.end - 1)
         })
      }
   }

   #[inline]
   pub fn start(&self) -> usize {
      self.start
   }

   #[inline]
   pub fn end(&self) -> usize {
      self.end
   }

   #[inline]
   pub fn consume_at(&mut self, marker: usize) {
      self.start = marker;
   }

   #[inline]
   pub fn consume(&mut self) {
      self.start = self.end;
   }

   #[inline]
   pub fn reserve(&mut self, additional: usize) {
      self.v.reserve(additional);
   }

   #[inline]
   pub fn rewind(&mut self, extra: usize) {
      if extra > (self.v.len() - self.end) {
         if self.start != self.end {
            for i in 0..(self.end - self.start) {
               self.v[i] = self.v[self.start + i].clone();
            }
         }

         self.end -= self.start;
         self.start = 0;
      }
   }

   #[inline]
   pub fn push(&mut self, value: T) {
      self.v[self.end] = value;
      self.end += 1;
   }
}

impl<T> Index<usize> for Ring<T> {
   type Output = T;

   #[inline]
   fn index(&self, index: usize) -> &T {
      &self.v[index]
   }
}

impl<T> Index<RangeFull> for Ring<T> {
   type Output = [T];

   #[inline]
   fn index(&self, _index: RangeFull) -> &[T] {
      &self.v[self.start..self.end]
   }
}

#[inline]
pub fn h_down_intersect(y: i64, p1: Point, p2: Point, points: &mut Ring<Point>) {
   if p2.y > y {
      if p1.y < y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
   } else {
      if p1.y > y && p2.y < y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
      points.push(p2);
   }
}

#[inline]
pub fn h_up_intersect(y: i64, p1: Point, p2: Point, points: &mut Ring<Point>) {
   if p2.y < y {
      if p1.y > y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
   } else {
      if p1.y < y && p2.y > y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
      points.push(p2);
   }
}

#[inline]
pub fn v_left_intersect(x: i64, p1: Point, p2: Point, points: &mut Ring<Point>) {
   if p2.x > x {
      if p1.x < x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
   } else {
      if p1.x > x && p2.x < x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
      points.push(p2);
   }
}

#[inline]
pub fn v_right_intersect(x: i64, p1: Point, p2: Point, points: &mut Ring<Point>) {
   if p2.x < x {
      if p1.x > x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
   } else {
      if p1.x < x && p2.x > x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
      points.push(p2);
   }
}

#[inline]
pub fn h_intersect(y: i64, p1: Point, p2: Point) -> i64 {
   p1.x + ((p2.x - p1.x) * (y - p1.y)).rounding_div(p2.y - p1.y)
}

#[inline]
pub fn v_intersect(x: i64, p1: Point, p2: Point) -> i64 {
   p1.y + ((p2.y - p1.y) * (x - p1.x)).rounding_div(p2.x - p1.x)
}

pub fn hv_clip<F>(intersect: F, at: i64, points: &mut Ring<Point>) where
   F: Fn(i64, Point, Point, &mut Ring<Point>),
{
   let start = points.start();
   let end = points.end();

   points.rewind(2 * (end - start));

   let rewinded_end = points.end();

   let mut p1 = points[end-1];

   for i in start..end {
      let p2 = points[i];

      intersect(at, p1, p2, points);

      p1 = p2;
   }

   points.consume_at(rewinded_end);
}

pub fn hv_split<F>(split: F, at: i64, write: &mut Ring<Point>, read_write: &mut Ring<Point>) where
   F: Fn(i64, Point, Point, &mut Ring<Point>, &mut Ring<Point>),
{
   let start = read_write.start();
   let end = read_write.end();

   let double = 2 * (end - start);
   read_write.rewind(double);
   write.rewind(double);

   let rewinded_end = read_write.end();

   assert!(end - start > 2);

   let mut p1 = read_write[end-1];

   for i in start..end {
      let p2 = read_write[i];

      split(at, p1, p2, write, read_write);

      p1 = p2;
   }

   read_write.consume_at(rewinded_end);
}

#[inline]
pub fn h_split_edge(y: i64, p1: Point, p2: Point, down: &mut Ring<Point>, up: &mut Ring<Point>) {
   if p2.y > y {
      if p1.y < y {
         let intersection = Point::new(h_intersect(y, p1, p2), y);
         down.push(intersection);
         up.push(intersection);
      }
      up.push(p2);
   } else if p2.y < y {
      if p1.y > y {
         let intersection = Point::new(h_intersect(y, p1, p2), y);
         down.push(intersection);
         up.push(intersection);
      }
      down.push(p2);
   } else {
      down.push(p2);
      up.push(p2);
   }
}

#[inline]
pub fn v_split_edge(x: i64, p1: Point, p2: Point, left: &mut Ring<Point>, right: &mut Ring<Point>) {
   if p2.x > x {
      if p1.x < x {
         let intersection = Point::new(x, v_intersect(x, p1, p2));
         left.push(intersection);
         right.push(intersection);
      }
      right.push(p2);
   } else if p2.x < x {
      if p1.x > x {
         let intersection = Point::new(x, v_intersect(x, p1, p2));
         left.push(intersection);
         right.push(intersection);
      }
      left.push(p2);
   } else {
      left.push(p2);
      right.push(p2);
   }
}

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

   use super::super::point::Point;

   use super::*;

   #[bench]
   fn bench_clip(b: &mut Bencher) {
      let mut points = Ring::new(1024 * 256);

      b.iter(|| {
         for _ in 0..1000 {
            points.consume();

            points.push(Point::new(50, 50));
            points.push(Point::new(100, 200));
            points.push(Point::new(150, 100));

            hv_clip(h_down_intersect, 150, &mut points);

            hv_clip(h_up_intersect, 80, &mut points);

            hv_clip(v_right_intersect, 70, &mut points);

            hv_clip(v_left_intersect, 140, &mut points);
         }
      });
   }

   #[test]
   fn test_clip() {
      let mut points = Ring::new(30);

      points.push(Point::new(50, 50));
      points.push(Point::new(100, 200));
      points.push(Point::new(150, 100));

      hv_clip(h_down_intersect, 150, &mut points);

      hv_clip(h_up_intersect, 80, &mut points);

      hv_clip(v_right_intersect, 70, &mut points);

      hv_clip(v_left_intersect, 140, &mut points);

      assert_eq!(points[..].len(), 7);

      assert_eq!(&points[..], [
         Point::new(140, 95),
         Point::new(110, 80),
         Point::new(70, 80),
         Point::new(70, 110),
         Point::new(83, 150),
         Point::new(125, 150),
         Point::new(140, 120),
      ]);
   }
}
<commit_msg>Ring::next_index and Ring::prev_index methods<commit_after>use std::iter::repeat;
use std::ops::{Index, RangeFull};
use std::fmt::Debug;

use super::point::Point;
use super::number::NumberOps;

#[derive(Debug)]
pub struct Ring<T> {
   v: Vec<T>,
   start: usize,
   end: usize,
}

impl<T> Ring<T> where T: Default + Clone + Debug {
   #[inline]
   pub fn new(capacity: usize) -> Self {
      let v = repeat(T::default()).take(capacity).collect();

      Ring { v: v, start: 0, end: 0 }
   }

   #[inline]
   pub fn len(&self) -> usize {
      self.end - self.start
   }

   #[inline]
   pub fn last(&self) -> Option<&T> {
      if self.start == self.end {
         None
      } else {
         Some(unsafe {
            self.v.get_unchecked(self.end - 1)
         })
      }
   }

   #[inline]
   pub fn start(&self) -> usize {
      self.start
   }

   #[inline]
   pub fn end(&self) -> usize {
      self.end
   }

   #[inline]
   pub fn consume_at(&mut self, marker: usize) {
      self.start = marker;
   }

   #[inline]
   pub fn consume(&mut self) {
      self.start = self.end;
   }

   #[inline]
   pub fn reserve(&mut self, additional: usize) {
      self.v.reserve(additional);
   }

   #[inline]
   pub fn rewind(&mut self, extra: usize) {
      if extra > (self.v.len() - self.end) {
         if self.start != self.end {
            for i in 0..(self.end - self.start) {
               self.v[i] = self.v[self.start + i].clone();
            }
         }

         self.end -= self.start;
         self.start = 0;
      }
   }

   #[inline]
   pub fn push(&mut self, value: T) {
      self.v[self.end] = value;
      self.end += 1;
   }

   #[inline]
   pub fn next_index(&self, index: usize) -> usize {
      let index = index + 1;
      if index == self.end {
         self.start
      } else {
         index
      }
   }

   #[inline]
   pub fn prev_index(&self, index: usize) -> usize {
      if index == self.start {
         self.end - 1
      } else {
         self.start - 1
      }
   }
}

impl<T> Index<usize> for Ring<T> {
   type Output = T;

   #[inline]
   fn index(&self, index: usize) -> &T {
      &self.v[index]
   }
}

impl<T> Index<RangeFull> for Ring<T> {
   type Output = [T];

   #[inline]
   fn index(&self, _index: RangeFull) -> &[T] {
      &self.v[self.start..self.end]
   }
}

#[inline]
pub fn h_down_intersect(y: i64, p1: Point, p2: Point, points: &mut Ring<Point>) {
   if p2.y > y {
      if p1.y < y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
   } else {
      if p1.y > y && p2.y < y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
      points.push(p2);
   }
}

#[inline]
pub fn h_up_intersect(y: i64, p1: Point, p2: Point, points: &mut Ring<Point>) {
   if p2.y < y {
      if p1.y > y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
   } else {
      if p1.y < y && p2.y > y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
      points.push(p2);
   }
}

#[inline]
pub fn v_left_intersect(x: i64, p1: Point, p2: Point, points: &mut Ring<Point>) {
   if p2.x > x {
      if p1.x < x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
   } else {
      if p1.x > x && p2.x < x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
      points.push(p2);
   }
}

#[inline]
pub fn v_right_intersect(x: i64, p1: Point, p2: Point, points: &mut Ring<Point>) {
   if p2.x < x {
      if p1.x > x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
   } else {
      if p1.x < x && p2.x > x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
      points.push(p2);
   }
}

#[inline]
pub fn h_intersect(y: i64, p1: Point, p2: Point) -> i64 {
   p1.x + ((p2.x - p1.x) * (y - p1.y)).rounding_div(p2.y - p1.y)
}

#[inline]
pub fn v_intersect(x: i64, p1: Point, p2: Point) -> i64 {
   p1.y + ((p2.y - p1.y) * (x - p1.x)).rounding_div(p2.x - p1.x)
}

pub fn hv_clip<F>(intersect: F, at: i64, points: &mut Ring<Point>) where
   F: Fn(i64, Point, Point, &mut Ring<Point>),
{
   let start = points.start();
   let end = points.end();

   points.rewind(2 * (end - start));

   let rewinded_end = points.end();

   let mut p1 = points[end-1];

   for i in start..end {
      let p2 = points[i];

      intersect(at, p1, p2, points);

      p1 = p2;
   }

   points.consume_at(rewinded_end);
}

pub fn hv_split<F>(split: F, at: i64, write: &mut Ring<Point>, read_write: &mut Ring<Point>) where
   F: Fn(i64, Point, Point, &mut Ring<Point>, &mut Ring<Point>),
{
   let start = read_write.start();
   let end = read_write.end();

   let double = 2 * (end - start);
   read_write.rewind(double);
   write.rewind(double);

   let rewinded_end = read_write.end();

   assert!(end - start > 2);

   let mut p1 = read_write[end-1];

   for i in start..end {
      let p2 = read_write[i];

      split(at, p1, p2, write, read_write);

      p1 = p2;
   }

   read_write.consume_at(rewinded_end);
}

#[inline]
pub fn h_split_edge(y: i64, p1: Point, p2: Point, down: &mut Ring<Point>, up: &mut Ring<Point>) {
   if p2.y > y {
      if p1.y < y {
         let intersection = Point::new(h_intersect(y, p1, p2), y);
         down.push(intersection);
         up.push(intersection);
      }
      up.push(p2);
   } else if p2.y < y {
      if p1.y > y {
         let intersection = Point::new(h_intersect(y, p1, p2), y);
         down.push(intersection);
         up.push(intersection);
      }
      down.push(p2);
   } else {
      down.push(p2);
      up.push(p2);
   }
}

#[inline]
pub fn v_split_edge(x: i64, p1: Point, p2: Point, left: &mut Ring<Point>, right: &mut Ring<Point>) {
   if p2.x > x {
      if p1.x < x {
         let intersection = Point::new(x, v_intersect(x, p1, p2));
         left.push(intersection);
         right.push(intersection);
      }
      right.push(p2);
   } else if p2.x < x {
      if p1.x > x {
         let intersection = Point::new(x, v_intersect(x, p1, p2));
         left.push(intersection);
         right.push(intersection);
      }
      left.push(p2);
   } else {
      left.push(p2);
      right.push(p2);
   }
}

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

   use super::super::point::Point;

   use super::*;

   #[bench]
   fn bench_clip(b: &mut Bencher) {
      let mut points = Ring::new(1024 * 256);

      b.iter(|| {
         for _ in 0..1000 {
            points.consume();

            points.push(Point::new(50, 50));
            points.push(Point::new(100, 200));
            points.push(Point::new(150, 100));

            hv_clip(h_down_intersect, 150, &mut points);

            hv_clip(h_up_intersect, 80, &mut points);

            hv_clip(v_right_intersect, 70, &mut points);

            hv_clip(v_left_intersect, 140, &mut points);
         }
      });
   }

   #[test]
   fn test_clip() {
      let mut points = Ring::new(30);

      points.push(Point::new(50, 50));
      points.push(Point::new(100, 200));
      points.push(Point::new(150, 100));

      hv_clip(h_down_intersect, 150, &mut points);

      hv_clip(h_up_intersect, 80, &mut points);

      hv_clip(v_right_intersect, 70, &mut points);

      hv_clip(v_left_intersect, 140, &mut points);

      assert_eq!(points[..].len(), 7);

      assert_eq!(&points[..], [
         Point::new(140, 95),
         Point::new(110, 80),
         Point::new(70, 80),
         Point::new(70, 110),
         Point::new(83, 150),
         Point::new(125, 150),
         Point::new(140, 120),
      ]);
   }
}
<|endoftext|>


<commit_before>use super::point::Point;
use super::number::NumberOps;

#[inline]
pub fn h_down_intersect(y: i64, p1: Point, p2: Point, points: &mut Vec<Point>) {
   if p2.y > y {
      if p1.y < y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
   } else {
      if p1.y > y && p2.y < y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
      points.push(p2);
   }
}

#[inline]
pub fn h_up_intersect(y: i64, p1: Point, p2: Point, points: &mut Vec<Point>) {
   if p2.y < y {
      if p1.y > y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
   } else {
      if p1.y < y && p2.y > y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
      points.push(p2);
   }
}

#[inline]
pub fn v_left_intersect(x: i64, p1: Point, p2: Point, points: &mut Vec<Point>) {
   if p2.x > x {
      if p1.x < x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
   } else {
      if p1.x > x && p2.x < x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
      points.push(p2);
   }
}

#[inline]
pub fn v_right_intersect(x: i64, p1: Point, p2: Point, points: &mut Vec<Point>) {
   if p2.x < x {
      if p1.x > x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
   } else {
      if p1.x < x && p2.x > x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
      points.push(p2);
   }
}

#[inline]
pub fn h_intersect(y: i64, p1: Point, p2: Point) -> i64 {
   p1.x + ((p2.x - p1.x) * (y - p1.y)).rounding_div(p2.y - p1.y)
}

#[inline]
pub fn v_intersect(x: i64, p1: Point, p2: Point) -> i64 {
   p1.y + ((p2.y - p1.y) * (x - p1.x)).rounding_div(p2.x - p1.x)
}

pub fn hv_clip<F>(intersect: F, y: i64, points: &mut Vec<Point>, start: usize) where
   F: Fn(i64, Point, Point, &mut Vec<Point>),
{
   let end = points.len();

   if end - start < 2 {
      return;
   }

   let mut p1 = points[end-1];

   for i in start..end {
      let p2 = points[i];
      intersect(y, p1, p2, points);

      p1 = p2;
   }
}

pub fn h_split(y: i64, start: usize, down: &mut Vec<Point>, up: &mut Vec<Point>) {
   let end = up.len();

   assert!(end - start > 2);

   let mut p1 = up[end-1];

   for i in start..end {
      let p2 = up[i];

      h_split_edge(y, p1, p2, down, up);

      p1 = p2;
   }
}

pub fn v_split(x: i64, start: usize, left: &mut Vec<Point>, right: &mut Vec<Point>) {
   let end = right.len();

   assert!(end - start > 2);

   let mut p1 = right[end-1];

   for i in start..end {
      let p2 = right[i];

      v_split_edge(x, p1, p2, left, right);

      p1 = p2;
   }
}

#[inline]
pub fn h_split_edge(y: i64, p1: Point, p2: Point, down: &mut Vec<Point>, up: &mut Vec<Point>) {
   if p2.y > y {
      if p1.y < y {
         let intersection = Point::new(h_intersect(y, p1, p2), y);
         down.push(intersection);
         up.push(intersection);
      }
      up.push(p2);
   } else if p2.y < y {
      if p1.y > y {
         let intersection = Point::new(h_intersect(y, p1, p2), y);
         down.push(intersection);
         up.push(intersection);
      }
      down.push(p2);
   } else {
      down.push(p2);
      up.push(p2);
   }
}

#[inline]
pub fn v_split_edge(x: i64, p1: Point, p2: Point, left: &mut Vec<Point>, right: &mut Vec<Point>) {
   if p2.x > x {
      if p1.x < x {
         let intersection = Point::new(x, v_intersect(x, p1, p2));
         left.push(intersection);
         right.push(intersection);
      }
      right.push(p2);
   } else if p2.x < x {
      if p1.x > x {
         let intersection = Point::new(x, v_intersect(x, p1, p2));
         left.push(intersection);
         right.push(intersection);
      }
      left.push(p2);
   } else {
      left.push(p2);
      right.push(p2);
   }
}

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

   use super::super::point::Point;

   use super::*;

   #[bench]
   fn bench_clip(b: &mut Bencher) {
      b.iter(|| {
         for _ in 0..1000 {
            let mut points = vec![
               Point::new(50, 50),
               Point::new(100, 200),
               Point::new(150, 100),
            ];
            points.reserve(30);

            let start = 0;
            let end = points.len();
            hv_clip(h_down_intersect, 150, &mut points, start);

            let start = end;
            let end = points.len();
            hv_clip(h_up_intersect, 80, &mut points, start);

            let start = end;
            let end = points.len();
            hv_clip(v_right_intersect, 70, &mut points, start);

            let start = end;
            hv_clip(v_left_intersect, 140, &mut points, start);
         }
      });
   }

   #[test]
   fn test_clip() {
      let mut points = vec![
         Point::new(50, 50),
         Point::new(100, 200),
         Point::new(150, 100),
      ];

      let start = 0;
      let end = points.len();
      hv_clip(h_down_intersect, 150, &mut points, start);

      let start = end;
      let end = points.len();
      hv_clip(h_up_intersect, 80, &mut points, start);

      let start = end;
      let end = points.len();
      hv_clip(v_right_intersect, 70, &mut points, start);

      let start = end;
      let end = points.len();
      hv_clip(v_left_intersect, 140, &mut points, start);

      assert_eq!(points.len(), 25);

      let (_, result) = points.split_at(end);
      assert_eq!(result, [
         Point::new(140, 95),
         Point::new(110, 80),
         Point::new(70, 80),
         Point::new(70, 110),
         Point::new(83, 150),
         Point::new(125, 150),
         Point::new(140, 120),
      ]);
   }
}
<commit_msg>Ring vector implementation<commit_after>use std::iter::repeat;
use std::ops::{Index, RangeFull};
use std::fmt::Debug;

use super::point::Point;
use super::number::NumberOps;

#[derive(Debug)]
pub struct Ring<T> {
   v: Vec<T>,
   start: usize,
   end: usize,
}

impl<T> Ring<T> where T: Default + Clone + Debug {
   #[inline]
   pub fn new(capacity: usize) -> Self {
      let v = repeat(T::default()).take(capacity).collect();

      Ring { v: v, start: 0, end: 0 }
   }

   #[inline]
   pub fn len(&self) -> usize {
      self.end - self.start
   }

   #[inline]
   pub fn last(&self) -> Option<&T> {
      self.v.last()
   }

   #[inline]
   pub fn start(&self) -> usize {
      self.start
   }

   #[inline]
   pub fn end(&self) -> usize {
      self.end
   }

   #[inline]
   pub fn consume(&mut self, marker: usize) {
      self.start = marker;
   }

   #[inline]
   pub fn reserve(&mut self, additional: usize) {
      self.v.reserve(additional);
   }

   #[inline]
   pub fn check_rewind(&mut self, extra: usize) {
      if extra > (self.v.len() - self.end) {
         if self.start != self.end {
            for i in 0..(self.end - self.start) {
               self.v[i] = self.v[self.start + i].clone();
            }
         }

         self.end -= self.start;
         self.start = 0;
      }
   }

   #[inline]
   pub fn push(&mut self, value: T) {
      self.v[self.end] = value;
      self.end += 1;
   }
}

impl<T> Index<usize> for Ring<T> {
   type Output = T;

   #[inline]
   fn index(&self, index: usize) -> &T {
      &self.v[index]
   }
}

impl<T> Index<RangeFull> for Ring<T> {
   type Output = [T];

   #[inline]
   fn index(&self, _index: RangeFull) -> &[T] {
      &self.v[self.start..self.end]
   }
}

#[inline]
pub fn h_down_intersect(y: i64, p1: Point, p2: Point, points: &mut Ring<Point>) {
   if p2.y > y {
      if p1.y < y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
   } else {
      if p1.y > y && p2.y < y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
      points.push(p2);
   }
}

#[inline]
pub fn h_up_intersect(y: i64, p1: Point, p2: Point, points: &mut Ring<Point>) {
   if p2.y < y {
      if p1.y > y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
   } else {
      if p1.y < y && p2.y > y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
      points.push(p2);
   }
}

#[inline]
pub fn v_left_intersect(x: i64, p1: Point, p2: Point, points: &mut Ring<Point>) {
   if p2.x > x {
      if p1.x < x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
   } else {
      if p1.x > x && p2.x < x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
      points.push(p2);
   }
}

#[inline]
pub fn v_right_intersect(x: i64, p1: Point, p2: Point, points: &mut Ring<Point>) {
   if p2.x < x {
      if p1.x > x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
   } else {
      if p1.x < x && p2.x > x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
      points.push(p2);
   }
}

#[inline]
pub fn h_intersect(y: i64, p1: Point, p2: Point) -> i64 {
   p1.x + ((p2.x - p1.x) * (y - p1.y)).rounding_div(p2.y - p1.y)
}

#[inline]
pub fn v_intersect(x: i64, p1: Point, p2: Point) -> i64 {
   p1.y + ((p2.y - p1.y) * (x - p1.x)).rounding_div(p2.x - p1.x)
}

pub fn hv_clip<F>(intersect: F, y: i64, points: &mut Ring<Point>) where
   F: Fn(i64, Point, Point, &mut Ring<Point>),
{
   let start = points.start();
   let end = points.end();

   points.check_rewind(2 * (end - start));

   let rewinded_end = points.end();

   let mut p1 = points[end-1];

   for i in start..end {
      let p2 = points[i];

      intersect(y, p1, p2, points);

      p1 = p2;
   }

   points.consume(rewinded_end);
}

pub fn h_split(y: i64, start: usize, down: &mut Vec<Point>, up: &mut Vec<Point>) {
   let end = up.len();

   assert!(end - start > 2);

   let mut p1 = up[end-1];

   for i in start..end {
      let p2 = up[i];

      h_split_edge(y, p1, p2, down, up);

      p1 = p2;
   }
}

pub fn v_split(x: i64, start: usize, left: &mut Vec<Point>, right: &mut Vec<Point>) {
   let end = right.len();

   assert!(end - start > 2);

   let mut p1 = right[end-1];

   for i in start..end {
      let p2 = right[i];

      v_split_edge(x, p1, p2, left, right);

      p1 = p2;
   }
}

#[inline]
pub fn h_split_edge(y: i64, p1: Point, p2: Point, down: &mut Vec<Point>, up: &mut Vec<Point>) {
   if p2.y > y {
      if p1.y < y {
         let intersection = Point::new(h_intersect(y, p1, p2), y);
         down.push(intersection);
         up.push(intersection);
      }
      up.push(p2);
   } else if p2.y < y {
      if p1.y > y {
         let intersection = Point::new(h_intersect(y, p1, p2), y);
         down.push(intersection);
         up.push(intersection);
      }
      down.push(p2);
   } else {
      down.push(p2);
      up.push(p2);
   }
}

#[inline]
pub fn v_split_edge(x: i64, p1: Point, p2: Point, left: &mut Vec<Point>, right: &mut Vec<Point>) {
   if p2.x > x {
      if p1.x < x {
         let intersection = Point::new(x, v_intersect(x, p1, p2));
         left.push(intersection);
         right.push(intersection);
      }
      right.push(p2);
   } else if p2.x < x {
      if p1.x > x {
         let intersection = Point::new(x, v_intersect(x, p1, p2));
         left.push(intersection);
         right.push(intersection);
      }
      left.push(p2);
   } else {
      left.push(p2);
      right.push(p2);
   }
}

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

   use super::super::point::Point;

   use super::*;

   #[bench]
   fn bench_clip(b: &mut Bencher) {
      b.iter(|| {
         for _ in 0..1000 {
            let mut points = Ring::new(30);

            points.push(Point::new(50, 50));
            points.push(Point::new(100, 200));
            points.push(Point::new(150, 100));

            hv_clip(h_down_intersect, 150, &mut points);

            hv_clip(h_up_intersect, 80, &mut points);

            hv_clip(v_right_intersect, 70, &mut points);

            hv_clip(v_left_intersect, 140, &mut points);
         }
      });
   }
/*
   #[test]
   fn test_clip() {
      let mut points = Ring::new(30);

      points.push(Point::new(50, 50));
      points.push(Point::new(100, 200));
      points.push(Point::new(150, 100));

      hv_clip(h_down_intersect, 150, &mut points);

      hv_clip(h_up_intersect, 80, &mut points);

      hv_clip(v_right_intersect, 70, &mut points);

      hv_clip(v_left_intersect, 140, &mut points);

      assert_eq!(points[..].len(), 7);

      assert_eq!(&points[..], [
         Point::new(140, 95),
         Point::new(110, 80),
         Point::new(70, 80),
         Point::new(70, 110),
         Point::new(83, 150),
         Point::new(125, 150),
         Point::new(140, 120),
      ]);
   }
*/
}
<|endoftext|>


<commit_before>use std::cmp;
use std::fmt;
use std::mem;
use std::mem::MaybeUninit;
use std::sync::atomic::{AtomicUsize, Ordering};

use crate::errors::InvalidThreadAccess;

fn next_thread_id() -> usize {
    static mut COUNTER: AtomicUsize = AtomicUsize::new(0);
    unsafe { COUNTER.fetch_add(1, Ordering::SeqCst) }
}

pub(crate) fn get_thread_id() -> usize {
    thread_local!(static THREAD_ID: usize = next_thread_id());
    THREAD_ID.with(|&x| x)
}

/// A `Fragile<T>` wraps a non sendable `T` to be safely send to other threads.
///
/// Once the value has been wrapped it can be sent to other threads but access
/// to the value on those threads will fail.
///
/// If the value needs destruction and the fragile wrapper is on another thread
/// the destructor will panic.  Alternatively you can use `Sticky<T>` which is
/// not going to panic but might temporarily leak the value.
pub struct Fragile<T> {
    value: MaybeUninit<Box<T>>,
    thread_id: usize,
}

impl<T> Fragile<T> {
    /// Creates a new `Fragile` wrapping a `value`.
    ///
    /// The value that is moved into the `Fragile` can be non `Send` and
    /// will be anchored to the thread that created the object.  If the
    /// fragile wrapper type ends up being send from thread to thread
    /// only the original thread can interact with the value.
    pub fn new(value: T) -> Self {
        Fragile {
            value: MaybeUninit::new(Box::new(value)),
            thread_id: get_thread_id(),
        }
    }

    /// Returns `true` if the access is valid.
    ///
    /// This will be `false` if the value was sent to another thread.
    pub fn is_valid(&self) -> bool {
        get_thread_id() == self.thread_id
    }

    #[inline(always)]
    fn assert_thread(&self) {
        if !self.is_valid() {
            panic!("trying to access wrapped value in fragile container from incorrect thread.");
        }
    }

    /// Consumes the `Fragile`, returning the wrapped value.
    ///
    /// # Panics
    ///
    /// Panics if called from a different thread than the one where the
    /// original value was created.
    pub fn into_inner(mut self) -> T {
        self.assert_thread();
        unsafe {
            let rv = mem::replace(&mut self.value, MaybeUninit::uninit());
            mem::forget(self);
            *rv.assume_init()
        }
    }

    /// Consumes the `Fragile`, returning the wrapped value if successful.
    ///
    /// The wrapped value is returned if this is called from the same thread
    /// as the one where the original value was created, otherwise the
    /// `Fragile` is returned as `Err(self)`.
    pub fn try_into_inner(self) -> Result<T, Self> {
        if get_thread_id() == self.thread_id {
            Ok(self.into_inner())
        } else {
            Err(self)
        }
    }

    /// Immutably borrows the wrapped value.
    ///
    /// # Panics
    ///
    /// Panics if the calling thread is not the one that wrapped the value.
    /// For a non-panicking variant, use [`try_get`](#method.try_get`).
    pub fn get(&self) -> &T {
        self.assert_thread();
        unsafe { &*self.value.as_ptr() }
    }

    /// Mutably borrows the wrapped value.
    ///
    /// # Panics
    ///
    /// Panics if the calling thread is not the one that wrapped the value.
    /// For a non-panicking variant, use [`try_get_mut`](#method.try_get_mut`).
    pub fn get_mut(&mut self) -> &mut T {
        self.assert_thread();
        unsafe { &mut *self.value.as_mut_ptr() }
    }

    /// Tries to immutably borrow the wrapped value.
    ///
    /// Returns `None` if the calling thread is not the one that wrapped the value.
    pub fn try_get(&self) -> Result<&T, InvalidThreadAccess> {
        if get_thread_id() == self.thread_id {
            unsafe { Ok(&*self.value.as_ptr()) }
        } else {
            Err(InvalidThreadAccess)
        }
    }

    /// Tries to mutably borrow the wrapped value.
    ///
    /// Returns `None` if the calling thread is not the one that wrapped the value.
    pub fn try_get_mut(&mut self) -> Result<&mut T, InvalidThreadAccess> {
        if get_thread_id() == self.thread_id {
            unsafe { Ok(&mut *self.value.as_mut_ptr()) }
        } else {
            Err(InvalidThreadAccess)
        }
    }
}

impl<T> Drop for Fragile<T> {
    fn drop(&mut self) {
        if mem::needs_drop::<T>() {
            if get_thread_id() == self.thread_id {
                unsafe {
                    let rv = mem::replace(&mut self.value, MaybeUninit::uninit());
                    rv.assume_init();
                }
            } else {
                panic!("destructor of fragile object ran on wrong thread");
            }
        }
    }
}

impl<T> From<T> for Fragile<T> {
    #[inline]
    fn from(t: T) -> Fragile<T> {
        Fragile::new(t)
    }
}

impl<T: Clone> Clone for Fragile<T> {
    #[inline]
    fn clone(&self) -> Fragile<T> {
        Fragile::new(self.get().clone())
    }
}

impl<T: Default> Default for Fragile<T> {
    #[inline]
    fn default() -> Fragile<T> {
        Fragile::new(T::default())
    }
}

impl<T: PartialEq> PartialEq for Fragile<T> {
    #[inline]
    fn eq(&self, other: &Fragile<T>) -> bool {
        *self.get() == *other.get()
    }
}

impl<T: Eq> Eq for Fragile<T> {}

impl<T: PartialOrd> PartialOrd for Fragile<T> {
    #[inline]
    fn partial_cmp(&self, other: &Fragile<T>) -> Option<cmp::Ordering> {
        self.get().partial_cmp(&*other.get())
    }

    #[inline]
    fn lt(&self, other: &Fragile<T>) -> bool {
        *self.get() < *other.get()
    }

    #[inline]
    fn le(&self, other: &Fragile<T>) -> bool {
        *self.get() <= *other.get()
    }

    #[inline]
    fn gt(&self, other: &Fragile<T>) -> bool {
        *self.get() > *other.get()
    }

    #[inline]
    fn ge(&self, other: &Fragile<T>) -> bool {
        *self.get() >= *other.get()
    }
}

impl<T: Ord> Ord for Fragile<T> {
    #[inline]
    fn cmp(&self, other: &Fragile<T>) -> cmp::Ordering {
        self.get().cmp(&*other.get())
    }
}

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

impl<T: fmt::Debug> fmt::Debug for Fragile<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self.try_get() {
            Ok(value) => f.debug_struct("Fragile").field("value", value).finish(),
            Err(..) => {
                struct InvalidPlaceholder;
                impl fmt::Debug for InvalidPlaceholder {
                    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                        f.write_str("<invalid thread>")
                    }
                }

                f.debug_struct("Fragile")
                    .field("value", &InvalidPlaceholder)
                    .finish()
            }
        }
    }
}

// this type is sync because access can only ever happy from the same thread
// that created it originally.  All other threads will be able to safely
// call some basic operations on the reference and they will fail.
unsafe impl<T> Sync for Fragile<T> {}

// The entire point of this type is to be Send
unsafe impl<T> Send for Fragile<T> {}

#[test]
fn test_basic() {
    use std::thread;
    let val = Fragile::new(true);
    assert_eq!(val.to_string(), "true");
    assert_eq!(val.get(), &true);
    assert!(val.try_get().is_ok());
    thread::spawn(move || {
        assert!(val.try_get().is_err());
    })
    .join()
    .unwrap();
}

#[test]
fn test_mut() {
    let mut val = Fragile::new(true);
    *val.get_mut() = false;
    assert_eq!(val.to_string(), "false");
    assert_eq!(val.get(), &false);
}

#[test]
#[should_panic]
fn test_access_other_thread() {
    use std::thread;
    let val = Fragile::new(true);
    thread::spawn(move || {
        val.get();
    })
    .join()
    .unwrap();
}

#[test]
fn test_noop_drop_elsewhere() {
    use std::thread;
    let val = Fragile::new(true);
    thread::spawn(move || {
        // force the move
        val.try_get().ok();
    })
    .join()
    .unwrap();
}

#[test]
fn test_panic_on_drop_elsewhere() {
    use std::sync::atomic::{AtomicBool, Ordering};
    use std::sync::Arc;
    use std::thread;
    let was_called = Arc::new(AtomicBool::new(false));
    struct X(Arc<AtomicBool>);
    impl Drop for X {
        fn drop(&mut self) {
            self.0.store(true, Ordering::SeqCst);
        }
    }
    let val = Fragile::new(X(was_called.clone()));
    assert!(thread::spawn(move || {
        val.try_get().ok();
    })
    .join()
    .is_err());
    assert_eq!(was_called.load(Ordering::SeqCst), false);
}

#[test]
fn test_rc_sending() {
    use std::rc::Rc;
    use std::sync::mpsc::channel;
    use std::thread;

    let val = Fragile::new(Rc::new(true));
    let (tx, rx) = channel();

    let thread = thread::spawn(move || {
        assert!(val.try_get().is_err());
        let here = val;
        tx.send(here).unwrap();
    });

    let rv = rx.recv().unwrap();
    assert!(**rv.get());

    thread.join().unwrap();
}
<commit_msg>Silence clippy on an unsafe impl<commit_after>use std::cmp;
use std::fmt;
use std::mem;
use std::mem::MaybeUninit;
use std::sync::atomic::{AtomicUsize, Ordering};

use crate::errors::InvalidThreadAccess;

fn next_thread_id() -> usize {
    static mut COUNTER: AtomicUsize = AtomicUsize::new(0);
    unsafe { COUNTER.fetch_add(1, Ordering::SeqCst) }
}

pub(crate) fn get_thread_id() -> usize {
    thread_local!(static THREAD_ID: usize = next_thread_id());
    THREAD_ID.with(|&x| x)
}

/// A `Fragile<T>` wraps a non sendable `T` to be safely send to other threads.
///
/// Once the value has been wrapped it can be sent to other threads but access
/// to the value on those threads will fail.
///
/// If the value needs destruction and the fragile wrapper is on another thread
/// the destructor will panic.  Alternatively you can use `Sticky<T>` which is
/// not going to panic but might temporarily leak the value.
pub struct Fragile<T> {
    value: MaybeUninit<Box<T>>,
    thread_id: usize,
}

impl<T> Fragile<T> {
    /// Creates a new `Fragile` wrapping a `value`.
    ///
    /// The value that is moved into the `Fragile` can be non `Send` and
    /// will be anchored to the thread that created the object.  If the
    /// fragile wrapper type ends up being send from thread to thread
    /// only the original thread can interact with the value.
    pub fn new(value: T) -> Self {
        Fragile {
            value: MaybeUninit::new(Box::new(value)),
            thread_id: get_thread_id(),
        }
    }

    /// Returns `true` if the access is valid.
    ///
    /// This will be `false` if the value was sent to another thread.
    pub fn is_valid(&self) -> bool {
        get_thread_id() == self.thread_id
    }

    #[inline(always)]
    fn assert_thread(&self) {
        if !self.is_valid() {
            panic!("trying to access wrapped value in fragile container from incorrect thread.");
        }
    }

    /// Consumes the `Fragile`, returning the wrapped value.
    ///
    /// # Panics
    ///
    /// Panics if called from a different thread than the one where the
    /// original value was created.
    pub fn into_inner(mut self) -> T {
        self.assert_thread();
        unsafe {
            let rv = mem::replace(&mut self.value, MaybeUninit::uninit());
            mem::forget(self);
            *rv.assume_init()
        }
    }

    /// Consumes the `Fragile`, returning the wrapped value if successful.
    ///
    /// The wrapped value is returned if this is called from the same thread
    /// as the one where the original value was created, otherwise the
    /// `Fragile` is returned as `Err(self)`.
    pub fn try_into_inner(self) -> Result<T, Self> {
        if get_thread_id() == self.thread_id {
            Ok(self.into_inner())
        } else {
            Err(self)
        }
    }

    /// Immutably borrows the wrapped value.
    ///
    /// # Panics
    ///
    /// Panics if the calling thread is not the one that wrapped the value.
    /// For a non-panicking variant, use [`try_get`](#method.try_get`).
    pub fn get(&self) -> &T {
        self.assert_thread();
        unsafe { &*self.value.as_ptr() }
    }

    /// Mutably borrows the wrapped value.
    ///
    /// # Panics
    ///
    /// Panics if the calling thread is not the one that wrapped the value.
    /// For a non-panicking variant, use [`try_get_mut`](#method.try_get_mut`).
    pub fn get_mut(&mut self) -> &mut T {
        self.assert_thread();
        unsafe { &mut *self.value.as_mut_ptr() }
    }

    /// Tries to immutably borrow the wrapped value.
    ///
    /// Returns `None` if the calling thread is not the one that wrapped the value.
    pub fn try_get(&self) -> Result<&T, InvalidThreadAccess> {
        if get_thread_id() == self.thread_id {
            unsafe { Ok(&*self.value.as_ptr()) }
        } else {
            Err(InvalidThreadAccess)
        }
    }

    /// Tries to mutably borrow the wrapped value.
    ///
    /// Returns `None` if the calling thread is not the one that wrapped the value.
    pub fn try_get_mut(&mut self) -> Result<&mut T, InvalidThreadAccess> {
        if get_thread_id() == self.thread_id {
            unsafe { Ok(&mut *self.value.as_mut_ptr()) }
        } else {
            Err(InvalidThreadAccess)
        }
    }
}

impl<T> Drop for Fragile<T> {
    fn drop(&mut self) {
        if mem::needs_drop::<T>() {
            if get_thread_id() == self.thread_id {
                unsafe {
                    let rv = mem::replace(&mut self.value, MaybeUninit::uninit());
                    rv.assume_init();
                }
            } else {
                panic!("destructor of fragile object ran on wrong thread");
            }
        }
    }
}

impl<T> From<T> for Fragile<T> {
    #[inline]
    fn from(t: T) -> Fragile<T> {
        Fragile::new(t)
    }
}

impl<T: Clone> Clone for Fragile<T> {
    #[inline]
    fn clone(&self) -> Fragile<T> {
        Fragile::new(self.get().clone())
    }
}

impl<T: Default> Default for Fragile<T> {
    #[inline]
    fn default() -> Fragile<T> {
        Fragile::new(T::default())
    }
}

impl<T: PartialEq> PartialEq for Fragile<T> {
    #[inline]
    fn eq(&self, other: &Fragile<T>) -> bool {
        *self.get() == *other.get()
    }
}

impl<T: Eq> Eq for Fragile<T> {}

impl<T: PartialOrd> PartialOrd for Fragile<T> {
    #[inline]
    fn partial_cmp(&self, other: &Fragile<T>) -> Option<cmp::Ordering> {
        self.get().partial_cmp(&*other.get())
    }

    #[inline]
    fn lt(&self, other: &Fragile<T>) -> bool {
        *self.get() < *other.get()
    }

    #[inline]
    fn le(&self, other: &Fragile<T>) -> bool {
        *self.get() <= *other.get()
    }

    #[inline]
    fn gt(&self, other: &Fragile<T>) -> bool {
        *self.get() > *other.get()
    }

    #[inline]
    fn ge(&self, other: &Fragile<T>) -> bool {
        *self.get() >= *other.get()
    }
}

impl<T: Ord> Ord for Fragile<T> {
    #[inline]
    fn cmp(&self, other: &Fragile<T>) -> cmp::Ordering {
        self.get().cmp(&*other.get())
    }
}

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

impl<T: fmt::Debug> fmt::Debug for Fragile<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self.try_get() {
            Ok(value) => f.debug_struct("Fragile").field("value", value).finish(),
            Err(..) => {
                struct InvalidPlaceholder;
                impl fmt::Debug for InvalidPlaceholder {
                    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                        f.write_str("<invalid thread>")
                    }
                }

                f.debug_struct("Fragile")
                    .field("value", &InvalidPlaceholder)
                    .finish()
            }
        }
    }
}

// this type is sync because access can only ever happy from the same thread
// that created it originally.  All other threads will be able to safely
// call some basic operations on the reference and they will fail.
unsafe impl<T> Sync for Fragile<T> {}

// The entire point of this type is to be Send
#[allow(clippy::non_send_fields_in_send_ty)]
unsafe impl<T> Send for Fragile<T> {}

#[test]
fn test_basic() {
    use std::thread;
    let val = Fragile::new(true);
    assert_eq!(val.to_string(), "true");
    assert_eq!(val.get(), &true);
    assert!(val.try_get().is_ok());
    thread::spawn(move || {
        assert!(val.try_get().is_err());
    })
    .join()
    .unwrap();
}

#[test]
fn test_mut() {
    let mut val = Fragile::new(true);
    *val.get_mut() = false;
    assert_eq!(val.to_string(), "false");
    assert_eq!(val.get(), &false);
}

#[test]
#[should_panic]
fn test_access_other_thread() {
    use std::thread;
    let val = Fragile::new(true);
    thread::spawn(move || {
        val.get();
    })
    .join()
    .unwrap();
}

#[test]
fn test_noop_drop_elsewhere() {
    use std::thread;
    let val = Fragile::new(true);
    thread::spawn(move || {
        // force the move
        val.try_get().ok();
    })
    .join()
    .unwrap();
}

#[test]
fn test_panic_on_drop_elsewhere() {
    use std::sync::atomic::{AtomicBool, Ordering};
    use std::sync::Arc;
    use std::thread;
    let was_called = Arc::new(AtomicBool::new(false));
    struct X(Arc<AtomicBool>);
    impl Drop for X {
        fn drop(&mut self) {
            self.0.store(true, Ordering::SeqCst);
        }
    }
    let val = Fragile::new(X(was_called.clone()));
    assert!(thread::spawn(move || {
        val.try_get().ok();
    })
    .join()
    .is_err());
    assert_eq!(was_called.load(Ordering::SeqCst), false);
}

#[test]
fn test_rc_sending() {
    use std::rc::Rc;
    use std::sync::mpsc::channel;
    use std::thread;

    let val = Fragile::new(Rc::new(true));
    let (tx, rx) = channel();

    let thread = thread::spawn(move || {
        assert!(val.try_get().is_err());
        let here = val;
        tx.send(here).unwrap();
    });

    let rv = rx.recv().unwrap();
    assert!(**rv.get());

    thread.join().unwrap();
}
<|endoftext|>


<commit_before>use std::hash;
use std::cmp;

static STILL: u8 = 0;
static NORTH: u8 = 1;
static EAST: u8 = 2;
static SOUTH: u8 = 3;
static WEST: u8 = 4;

static DIRECTIONS: [u8; 5] = [STILL, NORTH, EAST, SOUTH, WEST];
static CARDINALS: [u8; 4] = [NORTH, EAST, SOUTH, WEST];

#[derive(Copy, Clone, Hash, Eq, PartialEq, PartialOrd, Ord, Debug)]
struct Location{
	x: u16,
	y; u16,
};

#[derive(Copy, Clone, Eq, Debug)]
struct Site {
	owner: u8;
	strength: u8;
	production: u8;
};

#[derive(Copy, Clone, Debug)]
struct GameMap {
	contents: Vec< Vec<Site> >;
	width: u16, //Number of columns.
	height: u16, //Number of rows.
}

trait GameMapUtils {
	fn inBounds(&self) -> bool;
	fn getDistance(&self, l1: Location, l2: Location) -> u16;
	fn getAngle(&self, l1: Location, l2: Location) -> f64;
	fn getLocation(&self, l: Location, d: u8) -> Location;
	fn getSite(&self, l: Location, d: u8) -> &Site {
		let loc = self.getLocation(l, d);
		return self.contents
	}
}

macro_rules! getSite

	GameMap() {
		width = 0;
		height = 0;
		contents = std::vector< std::vector<Site> >(height, std::vector<Site>(width, { 0, 0, 0 }));
	}
	GameMap(const GameMap &otherMap) {
		width = otherMap.width;
		height = otherMap.height;
		contents = otherMap.contents;
	}
	GameMap(int width, int height) {
		width = width;
		height = height;
		contents = std::vector< std::vector<Site> >(height, std::vector<Site>(width, { 0, 0, 0 }));
	}

	bool inBounds(Location l) {
		return l.x < width && l.y < height;
	}
	float getDistance(Location l1, Location l2) {
		short dx = abs(l1.x - l2.x), dy = abs(l1.y - l2.y);
		if(dx > width / 2) dx = width - dx;
		if(dy > height / 2) dy = height - dy;
		return dx + dy;
	}
	float getAngle(Location l1, Location l2) {
		short dx = l2.x - l1.x, dy = l2.y - l1.y;
		if(dx > width - dx) dx -= width;
		else if(-dx > width + dx) dx += width;
		if(dy > height - dy) dy -= height;
		else if(-dy > height + dy) dy += height;
		return atan2(dy, dx);
	}

	Location getLocation(Location l, unsigned char direction) {
		if(direction != STILL) {
			if(direction == NORTH) {
				if(l.y == 0) l.y = height - 1;
				else l.y--;
			}
			else if(direction == EAST) {
				if(l.x == width - 1) l.x = 0;
				else l.x++;
			}
			else if(direction == SOUTH) {
				if(l.y == height - 1) l.y = 0;
				else l.y++;
			}
			else if(direction == WEST) {
				if(l.x == 0) l.x = width - 1;
				else l.x--;
			}
		}
		return l;
	}
	Site& getSite(Location l, unsigned char direction = STILL) {
		l = getLocation(l, direction);
		return contents[l.y][l.x];
	}
};

struct Move{
	Location loc; unsigned char dir;
};
static bool operator<(const Move& m1, const Move& m2) {
	unsigned int l1Prod = ((m1.loc.x + m1.loc.y)*((unsigned int)m1.loc.x + m1.loc.y + 1) / 2) + m1.loc.y, l2Prod = ((m2.loc.x + m2.loc.y)*((unsigned int)m2.loc.x + m2.loc.y + 1) / 2) + m2.loc.y;
	return ((l1Prod + m1.dir)*(l1Prod + m1.dir + 1) / 2) + m1.dir < ((l2Prod + m2.dir)*(l2Prod + m2.dir + 1) / 2) + m2.dir;
}<commit_msg>Added more rust<commit_after>use std::hash;
use std::cmp;
use std::f64;

static STILL: u8 = 0;
static NORTH: u8 = 1;
static EAST: u8 = 2;
static SOUTH: u8 = 3;
static WEST: u8 = 4;

static DIRECTIONS: [u8; 5] = [STILL, NORTH, EAST, SOUTH, WEST];
static CARDINALS: [u8; 4] = [NORTH, EAST, SOUTH, WEST];

#[derive(Copy, Clone, Hash, Eq, PartialEq, PartialOrd, Ord, Debug)]
struct Location{
	x: u16,
	y; u16,
};

#[derive(Copy, Clone, Eq, Debug)]
struct Site {
	owner: u8;
	strength: u8;
	production: u8;
};

#[derive(Copy, Clone, Debug)]
struct GameMap {
	contents: Vec< Vec<Site> >;
	width: u16, //Number of columns.
	height: u16, //Number of rows.
}

trait GameMapUtils {
	fn inBounds(&self, l: Location) -> bool;
	fn getDistance(&self, l1: Location, l2: Location) -> u16;
	fn getAngle(&self, l1: Location, l2: Location) -> f64;
	fn getLocation(&self, l: Location, d: u8) -> Location;
	fn getSite(&self, l: Location, d: u8) -> &Site;
}

impl GameMapUtils for GameMap {
    fn inBounds(&self, l: Location) -> bool {
    	l.x < self.width && l.y < self.height
    }
    fn getDistance(&self, l: Location) -> u16 {
		let mut dx = (l1.x - l2.x).abs();
		let mut dy = (l1.y - l2.y).abs();
		if dx > self.width / 2 { dx = self.width - dx; }
		if dy > self.height / 2 { dy = self.height - dy; }
		dx + dy
    }
    fn getAngle(&self, l1: Location, l2: Location) -> bool {
		let mut dx = l2.x - l1.x;
		let mut dy = l2.y - l1.y;
		if dx > self.width - dx { dx -= self.width; }
		else if-dx > self.width + dx { dx += self.width; }
		if dy > self.height - dy { dy -= self.height; }
		else if -dy > self.height + dy { dy += self.height; }
		dy.atan2(dx)
    }
    fn getLocation(&self, l: Location, d: u8) -> Location {
    	let mut loc = Location { x: l1.x, y: l1.y };
    	if d == NORTH {
    		if loc.y == 0 { loc.y = self.height - 1; }
    		else loc.y -= 1;
    	} else if d == EAST {
    		if loc.x == self.width - 1 { loc.x = 0; }
    		else loc.x += 1;
    	} else if d == SOUTH {
    		if loc.y == self.height - 1 { loc.y = 0; }
    		else loc.y += 1;
    	} else if d == WEST {
    		if loc.x == 0 { loc.x = self.width - 1; }
    		else loc.x -= 1;
    	}
    	loc
    }
    fn getSite(&self, l: Location, d: u8) -> &Site {
    	let loc = self.getLocation(l, d);
    	self.contents[l.y][l.x]
    }
}

	GameMap() {
		width = 0;
		height = 0;
		contents = std::vector< std::vector<Site> >(height, std::vector<Site>(width, { 0, 0, 0 }));
	}
	GameMap(const GameMap &otherMap) {
		width = otherMap.width;
		height = otherMap.height;
		contents = otherMap.contents;
	}
	GameMap(int width, int height) {
		width = width;
		height = height;
		contents = std::vector< std::vector<Site> >(height, std::vector<Site>(width, { 0, 0, 0 }));
	}

	bool inBounds(Location l) {
		return l.x < width && l.y < height;
	}
	float getDistance(Location l1, Location l2) {
		short dx = abs(l1.x - l2.x), dy = abs(l1.y - l2.y);
		if(dx > width / 2) dx = width - dx;
		if(dy > height / 2) dy = height - dy;
		return dx + dy;
	}
	float getAngle(Location l1, Location l2) {
		short dx = l2.x - l1.x, dy = l2.y - l1.y;
		if(dx > width - dx) dx -= width;
		else if(-dx > width + dx) dx += width;
		if(dy > height - dy) dy -= height;
		else if(-dy > height + dy) dy += height;
		return atan2(dy, dx);
	}

	Location getLocation(Location l, unsigned char direction) {
		if(direction != STILL) {
			if(direction == NORTH) {
				if(l.y == 0) l.y = height - 1;
				else l.y--;
			}
			else if(direction == EAST) {
				if(l.x == width - 1) l.x = 0;
				else l.x++;
			}
			else if(direction == SOUTH) {
				if(l.y == height - 1) l.y = 0;
				else l.y++;
			}
			else if(direction == WEST) {
				if(l.x == 0) l.x = width - 1;
				else l.x--;
			}
		}
		return l;
	}
	Site& getSite(Location l, unsigned char direction = STILL) {
		l = getLocation(l, direction);
		return contents[l.y][l.x];
	}
};

struct Move{
	Location loc; unsigned char dir;
};
static bool operator<(const Move& m1, const Move& m2) {
	unsigned int l1Prod = ((m1.loc.x + m1.loc.y)*((unsigned int)m1.loc.x + m1.loc.y + 1) / 2) + m1.loc.y, l2Prod = ((m2.loc.x + m2.loc.y)*((unsigned int)m2.loc.x + m2.loc.y + 1) / 2) + m2.loc.y;
	return ((l1Prod + m1.dir)*(l1Prod + m1.dir + 1) / 2) + m1.dir < ((l2Prod + m2.dir)*(l2Prod + m2.dir + 1) / 2) + m2.dir;
}<|endoftext|>


<commit_before>/// Used to define a property.
#[macro_export]
macro_rules! property {
    ($(#[$property_doc:meta])* $property:ident($type:ty)) => {
        #[derive(Default, Debug, Clone, PartialEq)]
        $(#[$property_doc])*
        pub struct $property(pub $type);

        impl $property {
            /// Returns the value of a property.
            pub fn get(entity: Entity, ecm: &EntityComponentManager) -> $type {
                get_property::<$property>(entity, ecm).0
            }
        }

        impl<T: Into<$property>> From<T> for PropertySource<$property> {
            fn from(value: T) -> Self {
                PropertySource::Value(value.into())
            }
        }

        impl From<$property> for $type {
            fn from(property: $property) -> $type {
                property.0.into()
            }
        }

        impl From<$type> for $property {
            fn from(value: $type) -> $property {
                $property(value)
            }
        }
    };
}

/// Used to define a widget, with properties and event handlers.
#[macro_export]
macro_rules! widget {
    ( $(#[$widget_doc:meta])* $widget:ident $(<$state:ident>)* $(: $( $handler:ident ),*)* $( { $($(#[$prop_doc:meta])* $property:ident: $property_type:tt ),* } )* ) => {
        $(#[$widget_doc])*
        #[derive(Default)]
        pub struct $widget {
            attached_properties: HashMap<TypeId, ComponentBox>,
            shared_attached_properties: HashMap<TypeId, SharedComponentBox>,
            event_handlers: Vec<Rc<dyn EventHandler>>,
            bounds: Bounds,
            constraint: Constraint,
            name: Option<Name>,
            horizontal_alignment: HorizontalAlignment,
            vertical_alignment: VerticalAlignment,
            margin: Margin,
            enabled: Enabled,
            visibility: Visibility,
            _empty: Option<RefCell<i32>>,
             $(
                $(
                    $property: Option<PropertySource<$property_type>>,
                )*
             )*
            children: Vec<Entity>,
            $(
                state: RefCell<Option<Rc<$state>>>
            )*
        }

        impl $widget {
            /// Sets or shares an attached property.
            pub fn attach<P: Component + PartialEq + Debug>(mut self, property: impl Into<PropertySource<P>>) -> Self {
                match property.into() {
                    PropertySource::Value(value) => {
                        self.attached_properties.insert(TypeId::of::<P>(), ComponentBox::new(value));
                    },
                    PropertySource::Source(source) => {
                        self.shared_attached_properties.insert(TypeId::of::<P>(), SharedComponentBox::new(TypeId::of::<P>(), source));
                    }
                }
                self
            }

            /// Shares an attached property.
            pub fn attach_by_source<P: Component>(mut self, source: Entity) -> Self {
                 self.shared_attached_properties.insert(TypeId::of::<P>(), SharedComponentBox::new(TypeId::of::<P>(), source));
                self
            }

             /// Sets or shares the constraint property.
            pub fn constraint<P: Into<PropertySource<Constraint>>>(mut self, constraint: P) -> Self {
                match constraint.into() {
                    PropertySource::Value(value) => {
                        self.constraint = value;
                    },
                    PropertySource::Source(source) => {
                        self.shared_attached_properties.insert(TypeId::of::<Constraint>(), SharedComponentBox::new(TypeId::of::<Constraint>(), source));
                    }
                }
                self
            }

            /// Sets or shares the vertical alignment property.
            pub fn vertical_alignment<P: Into<PropertySource<VerticalAlignment>>>(self, vertical_alignment: P) -> Self {
                self.attach(vertical_alignment)
            }

            /// Sets or shares the horizontal alignment property.
            pub fn horizontal_alignment<P: Into<PropertySource<HorizontalAlignment>>>(self, horizontal_alignment: P) -> Self {
                self.attach(horizontal_alignment)
            }

            /// Sets or shares the visibility property.
            pub fn visibility<P: Into<PropertySource<Visibility>>>(self, visibility: P) -> Self {
                self.attach(visibility)
            }

            /// Sets or shares the margin property.
            pub fn margin<P: Into<PropertySource<Margin>>>(self, margin: P) -> Self {
                self.attach(margin)
            }

            /// Sets or shares the enabled property.
            pub fn enabled<P: Into<PropertySource<Enabled>>>(self, enabled: P) -> Self {
                self.attach(enabled)
            }

            /// Inserts a new width.
            pub fn width(mut self, width: f64) -> Self {
                self.constraint.set_width(width);
                self
            }

            /// Inserts a new height.
            pub fn height(mut self, height: f64) -> Self {
                self.constraint.set_height(height);
                self
            }

            /// Inserts a new size.
            pub fn size(mut self, width: f64, height: f64) -> Self {
                self.constraint.set_width(width);
                self.constraint.set_height(height);
                self
            }

            /// Inserts a new min_width.
            pub fn min_width(mut self, min_width: f64) -> Self {
                self.constraint.set_min_width(min_width);
                self
            }

            /// Inserts a new min_height.
            pub fn min_height(mut self, min_height: f64) -> Self {
                self.constraint.set_min_height(min_height);
                self
            }

            /// Inserts a new min_size.
            pub fn min_size(mut self, min_width: f64, min_height: f64) -> Self {
                self.constraint.set_min_width(min_width);
                self.constraint.set_min_height(min_height);
                self
            }

            /// Inserts a new max_width.
            pub fn max_width(mut self, max_width: f64) -> Self {
                self.constraint.set_max_width(max_width);
                self
            }

            /// Inserts a new max_height.
            pub fn max_height(mut self, max_height: f64) -> Self {
                self.constraint.set_max_height(max_height);
                self
            }

            /// Inserts a new min_size.
            pub fn max_size(mut self, max_width: f64, max_height: f64) -> Self {
                self.constraint.set_max_width(max_width);
                self.constraint.set_max_height(max_height);
                self
            }

            /// Sets the debug name of the widget.
            pub fn name<P: Into<Name>>(mut self, name: P) -> Self {
                self.name = Some(name.into());
                self
            }

            $(
                /// Returns the cloned state of the widget.
                pub fn clone_state(&self) -> Rc<$state> {
                    if let Some(state) = &*self.state.borrow() {
                        return state.clone();
                    }

                    let state = Rc::new($state::default());
                    *self.state.borrow_mut() = Some(state.clone());

                    state
                }
            )*

            $(
                $(
                    $(#[$prop_doc])*
                    pub fn $property<P: Into<PropertySource<$property_type>>>(mut self, $property: P) -> Self {
                        if !self.$property.is_none() {
                            return self;
                        }

                        self.$property = Some($property.into());
                        self
                    }
                )*
            )*
        }

        $(
            $(
                impl $handler for $widget {}
            )*
        )*

        impl Widget for $widget {
            fn create() -> Self {
                $widget {
                    event_handlers: vec![],
                    enabled: Enabled(true),
                    $(
                        $(
                            $property: None,
                        )*
                    )*
                    children: vec![],
                    ..Default::default()
                }
            }

            fn insert_handler(mut self, handler: impl Into<Rc<dyn EventHandler>>) -> Self {
                self.event_handlers.push(handler.into());
                self
            }

            fn child(mut self, child: Entity) -> Self {
                self.children.push(child);
                self
            }

            $(
                fn state(&self) -> Option<Rc<State>> {
                    if self.state.borrow().is_none() {
                        *self.state.borrow_mut() = Some(Rc::new($state::default()));
                    }

                    if let Some(state) = &*self.state.borrow() {
                        return Some(state.clone())
                    }

                    None
                }
            )*

            fn build(self, context: &mut BuildContext) -> Entity {
                let entity = context.create_entity();

                let this = self.template(entity, context);

                if let Some(render_object) = this.render_object() {
                    context.register_render_object(entity, render_object);
                }

                context.register_layout(entity, this.layout());

                 // register state
                if let Some(state) = &this.state() {
                     context.register_state(entity, state.clone());
                 }

                // register default set of properties
                context.register_property(entity, this.bounds);
                context.register_property(entity, this.constraint);
                context.register_property(entity, this.vertical_alignment);
                context.register_property(entity, this.horizontal_alignment);
                context.register_property(entity, this.visibility);
                context.register_property(entity, this.margin);
                context.register_property(entity, this.enabled);

                // register helpers
                context.register_property(entity, Point::default());

                // register attached properties
                for (_, property) in this.attached_properties {
                    context.register_property_box(entity, property);
                }

                for (_, property) in this.shared_attached_properties {
                    context.register_property_shared_box(entity, property);
                }

                // register properties
                $(
                    $(
                        if let Some($property) = this.$property {
                            match $property {
                                PropertySource::Value(value) => {
                                    context.register_property(entity, value);
                                },
                                PropertySource::Source(source) => {
                                    context.register_shared_property::<$property_type>(entity, source);
                                }
                            }
                        }
                    )*
                )*

                // register event handlers
                for handler in this.event_handlers {
                    context.register_handler(entity, handler);
                }

                // register name
                if let Some(name) = this.name {
                    context.register_property(entity, name);
                }

                for child in this.children {
                    context.append_child(entity, child);
                }

                entity
            }
        }
    };
}
<commit_msg>[fix] constraint<commit_after>/// Used to define a property.
#[macro_export]
macro_rules! property {
    ($(#[$property_doc:meta])* $property:ident($type:ty)) => {
        #[derive(Default, Debug, Clone, PartialEq)]
        $(#[$property_doc])*
        pub struct $property(pub $type);

        impl $property {
            /// Returns the value of a property.
            pub fn get(entity: Entity, ecm: &EntityComponentManager) -> $type {
                get_property::<$property>(entity, ecm).0
            }
        }

        impl<T: Into<$property>> From<T> for PropertySource<$property> {
            fn from(value: T) -> Self {
                PropertySource::Value(value.into())
            }
        }

        impl From<$property> for $type {
            fn from(property: $property) -> $type {
                property.0.into()
            }
        }

        impl From<$type> for $property {
            fn from(value: $type) -> $property {
                $property(value)
            }
        }
    };
}

/// Used to define a widget, with properties and event handlers.
#[macro_export]
macro_rules! widget {
    ( $(#[$widget_doc:meta])* $widget:ident $(<$state:ident>)* $(: $( $handler:ident ),*)* $( { $($(#[$prop_doc:meta])* $property:ident: $property_type:tt ),* } )* ) => {
        $(#[$widget_doc])*
        #[derive(Default)]
        pub struct $widget {
            attached_properties: HashMap<TypeId, ComponentBox>,
            shared_attached_properties: HashMap<TypeId, SharedComponentBox>,
            event_handlers: Vec<Rc<dyn EventHandler>>,
            bounds: Bounds,
            min_width: Option<f64>,
            min_height: Option<f64>,
            max_width: Option<f64>,
            max_height: Option<f64>,
            width: Option<f64>,
            height: Option<f64>,
            name: Option<Name>,
            horizontal_alignment: HorizontalAlignment,
            vertical_alignment: VerticalAlignment,
            margin: Margin,
            enabled: Enabled,
            visibility: Visibility,
            _empty: Option<RefCell<i32>>,
             $(
                $(
                    $property: Option<PropertySource<$property_type>>,
                )*
             )*
            children: Vec<Entity>,
            $(
                state: RefCell<Option<Rc<$state>>>
            )*
        }

        impl $widget {
            /// Sets or shares an attached property.
            pub fn attach<P: Component + PartialEq + Debug>(mut self, property: impl Into<PropertySource<P>>) -> Self {
                match property.into() {
                    PropertySource::Value(value) => {
                        self.attached_properties.insert(TypeId::of::<P>(), ComponentBox::new(value));
                    },
                    PropertySource::Source(source) => {
                        self.shared_attached_properties.insert(TypeId::of::<P>(), SharedComponentBox::new(TypeId::of::<P>(), source));
                    }
                }
                self
            }

            /// Shares an attached property.
            pub fn attach_by_source<P: Component>(mut self, source: Entity) -> Self {
                 self.shared_attached_properties.insert(TypeId::of::<P>(), SharedComponentBox::new(TypeId::of::<P>(), source));
                self
            }

             /// Sets or shares the constraint property.
            pub fn constraint<P: Into<PropertySource<Constraint>>>(mut self, constraint: P) -> Self {
                self.attach(constraint)
            }

            /// Sets or shares the vertical alignment property.
            pub fn vertical_alignment<P: Into<PropertySource<VerticalAlignment>>>(self, vertical_alignment: P) -> Self {
                self.attach(vertical_alignment)
            }

            /// Sets or shares the horizontal alignment property.
            pub fn horizontal_alignment<P: Into<PropertySource<HorizontalAlignment>>>(self, horizontal_alignment: P) -> Self {
                self.attach(horizontal_alignment)
            }

            /// Sets or shares the visibility property.
            pub fn visibility<P: Into<PropertySource<Visibility>>>(self, visibility: P) -> Self {
                self.attach(visibility)
            }

            /// Sets or shares the margin property.
            pub fn margin<P: Into<PropertySource<Margin>>>(self, margin: P) -> Self {
                self.attach(margin)
            }

            /// Sets or shares the enabled property.
            pub fn enabled<P: Into<PropertySource<Enabled>>>(self, enabled: P) -> Self {
                self.attach(enabled)
            }

            /// Inserts a new width.
            pub fn width(mut self, width: f64) -> Self {
                if !self.width.is_none() {
                    return self;
                }
                self.width = Some(width);
                self
            }

            /// Inserts a new height.
            pub fn height(mut self, height: f64) -> Self {
                if !self.height.is_none() {
                    return self;
                }
                self.height = Some(height);
                self
            }

            /// Inserts a new size.
            pub fn size(mut self, width: f64, height: f64) -> Self {
                if self.width.is_none() {
                    self.width = Some(width);
                }
                if self.height.is_none() {
                    self.height = Some(height);
                }
                self
            }

            /// Inserts a new min_width.
            pub fn min_width(mut self, min_width: f64) -> Self {
                if !self.min_width.is_none() {
                    return self;
                }
                self.min_width = Some(min_width);
                self
            }

            /// Inserts a new min_height.
            pub fn min_height(mut self, min_height: f64) -> Self {
                if !self.min_height.is_none() {
                    return self;
                }
                self.min_height = Some(min_height);
                self
            }

            /// Inserts a new min_size.
            pub fn min_size(mut self, min_width: f64, min_height: f64) -> Self {
                if self.min_width.is_none() {
                    self.min_width = Some(min_width);
                }
                if self.min_height.is_none() {
                    self.min_height = Some(min_height);
                }
                self
            }

            /// Inserts a new max_width.
            pub fn max_width(mut self, max_width: f64) -> Self {
                if !self.max_width.is_none() {
                    return self;
                }
                self.max_width = Some(max_width);
                self
            }

            /// Inserts a new max_height.
            pub fn max_height(mut self, max_height: f64) -> Self {
                if !self.max_height.is_none() {
                    return self;
                }
                self.max_height = Some(max_height);
                self
            }

            /// Inserts a new min_size.
            pub fn max_size(mut self, max_width: f64, max_height: f64) -> Self {
                if self.max_width.is_none() {
                    self.max_width = Some(max_width);
                }
                if self.max_height.is_none() {
                    self.max_height = Some(max_height);
                }
                self
            }

            /// Sets the debug name of the widget.
            pub fn name<P: Into<Name>>(mut self, name: P) -> Self {
                self.name = Some(name.into());
                self
            }

            $(
                /// Returns the cloned state of the widget.
                pub fn clone_state(&self) -> Rc<$state> {
                    if let Some(state) = &*self.state.borrow() {
                        return state.clone();
                    }

                    let state = Rc::new($state::default());
                    *self.state.borrow_mut() = Some(state.clone());

                    state
                }
            )*

            $(
                $(
                    $(#[$prop_doc])*
                    pub fn $property<P: Into<PropertySource<$property_type>>>(mut self, $property: P) -> Self {
                        if !self.$property.is_none() {
                            return self;
                        }

                        self.$property = Some($property.into());
                        self
                    }
                )*
            )*
        }

        $(
            $(
                impl $handler for $widget {}
            )*
        )*

        impl Widget for $widget {
            fn create() -> Self {
                $widget {
                    event_handlers: vec![],
                    enabled: Enabled(true),
                    $(
                        $(
                            $property: None,
                        )*
                    )*
                    children: vec![],
                    ..Default::default()
                }
            }

            fn insert_handler(mut self, handler: impl Into<Rc<dyn EventHandler>>) -> Self {
                self.event_handlers.push(handler.into());
                self
            }

            fn child(mut self, child: Entity) -> Self {
                self.children.push(child);
                self
            }

            $(
                fn state(&self) -> Option<Rc<State>> {
                    if self.state.borrow().is_none() {
                        *self.state.borrow_mut() = Some(Rc::new($state::default()));
                    }

                    if let Some(state) = &*self.state.borrow() {
                        return Some(state.clone())
                    }

                    None
                }
            )*

            fn build(self, context: &mut BuildContext) -> Entity {
                let entity = context.create_entity();

                let this = self.template(entity, context);

                if let Some(render_object) = this.render_object() {
                    context.register_render_object(entity, render_object);
                }

                context.register_layout(entity, this.layout());

                 // register state
                if let Some(state) = &this.state() {
                     context.register_state(entity, state.clone());
                 }

                // register default set of properties
                context.register_property(entity, this.bounds);
                context.register_property(entity, this.vertical_alignment);
                context.register_property(entity, this.horizontal_alignment);
                context.register_property(entity, this.visibility);
                context.register_property(entity, this.margin);
                context.register_property(entity, this.enabled);

                let mut constraint = Constraint::default();

                if let Some(width) = this.width {
                    constraint.set_width(width);
                }
                if let Some(height) = this.height {
                    constraint.set_height(height);
                }
                if let Some(min_width) = this.min_width {
                    constraint.set_min_width(min_width);
                }
                if let Some(min_height) = this.min_height {
                    constraint.set_min_height(min_height);
                }
                if let Some(max_width) = this.max_width {
                    constraint.set_max_width(max_width);
                }
                if let Some(max_height) = this.max_height {
                    constraint.set_max_height(max_height);
                }
                context.register_property(entity, constraint);

                // register helpers
                context.register_property(entity, Point::default());

                // register attached properties
                for (_, property) in this.attached_properties {
                    context.register_property_box(entity, property);
                }

                for (_, property) in this.shared_attached_properties {
                    context.register_property_shared_box(entity, property);
                }

                // register properties
                $(
                    $(
                        if let Some($property) = this.$property {
                            match $property {
                                PropertySource::Value(value) => {
                                    context.register_property(entity, value);
                                },
                                PropertySource::Source(source) => {
                                    context.register_shared_property::<$property_type>(entity, source);
                                }
                            }
                        }
                    )*
                )*

                // register event handlers
                for handler in this.event_handlers {
                    context.register_handler(entity, handler);
                }

                // register name
                if let Some(name) = this.name {
                    context.register_property(entity, name);
                }

                for child in this.children {
                    context.append_child(entity, child);
                }

                entity
            }
        }
    };
}
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! compile_prim(
    ($ty:ty, $type_name:ident, $make_constant:ident) => (
impl Compile for $ty {
    #[inline(always)]
    fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
        unsafe {
            NativeRef::from_ptr($make_constant(func.as_ptr(), $type_name, *self) )
        }
    }
    #[inline(always)]
    fn jit_type(_:Option<$ty>) -> Type {
        unsafe {
            NativeRef::from_ptr($type_name)
        }
    }
});
    ($ty:ty, $type_name:ident, $make_constant:ident, $cast:ty) => (
impl Compile for $ty {
    #[inline(always)]
    fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
        unsafe {
            NativeRef::from_ptr($make_constant(func.as_ptr(), $type_name, *self as $cast) )
        }
    }
    #[inline(always)]
    fn jit_type(_:Option<$ty>) -> Type {
        unsafe {
            NativeRef::from_ptr($type_name)
        }
    }
});
)

macro_rules! compile_func(
    (fn($($arg:ident),*) -> $ret:ty, $sig:ty) => (
    impl<$($arg:Compile,)* R:Compile> Compile for $sig {
        #[inline(always)]
        fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
            let ptr = (self as *const $sig).to_uint().compile(func);
            func.insn_convert(&ptr, get::<$sig>(), false)
        }
        #[inline(always)]
        fn jit_type(_:Option<$sig>) -> Type {
            Type::create_signature(CDECL, get::<R>(), [$(get::<$arg>()),*][mut])
        }
    })
)

macro_rules! compile_prims(
    ($(($ty:ty, $cast: ty) => ($type_name:ident, $make_constant:ident)),+) => (
        $(compile_prim!($ty, $type_name, $make_constant, $cast))+
    );
)

#[macro_export]
macro_rules! native_ref(
    ($name:ident, $field:ident, $pointer_ty:ty) => (
        #[allow(missing_copy_implementations)]
        #[deriving(PartialEq)]
        pub struct $name {
            $field: $pointer_ty
        }
        impl NativeRef for $name {
            #[inline(always)]
            /// Convert to a native pointer
            unsafe fn as_ptr(&self) -> $pointer_ty {
                self.$field
            }
            #[inline(always)]
            /// Convert from a native pointer
            unsafe fn from_ptr(ptr:$pointer_ty) -> $name {
                $name {
                    $field: ptr
                }
            }
        }
    );
    ($name:ident, $field:ident, $pointer_ty:ty, $lifetime:ident) => (
        #[deriving(PartialEq)]
        pub struct $name<'a> {
            $field: $pointer_ty,
            marker: $lifetime<'a>
        }
        impl<'a> NativeRef for $name<'a> {
            #[inline]
            /// Convert to a native pointer
            unsafe fn as_ptr(&self) -> $pointer_ty {
                self.$field
            }
            #[inline]
            /// Convert from a native pointer
            unsafe fn from_ptr<'a>(ptr:$pointer_ty) -> $name<'a> {
                $name {
                    $field: ptr,
                    marker: $lifetime::<'a>
                }
            }
        }
    )
)
#[macro_export]
macro_rules! jit(
    (struct {
        $($name:expr: $ty:ty),*
    }) => ({
        let structure = Type::create_struct([
            $(get::<$ty>()),*
        ].as_mut_slice());
        structure.set_names(&[$($name),*]);
        structure
    });
    (union {
        $($name:expr: $ty:ty),+
    }) => ({
        let structure = Type::create_union([
            $(get::<$ty>()),+
        ].as_mut_slice());
        structure.set_names(&[$($name),+]);
        structure
    });
    ($func:ident, return) => (
        $func.insn_default_return()
    );
    ($func:ident, return $($t:tt)+) => (
        $func.insn_return(jit!($($t)+))
    );
    ($func:ident, $var:ident += $num:expr) => (
        $func.insn_store($var, &$func.insn_add($var, $num));
    );
    ($func:ident, $var:ident -= $num:expr) => (
        $func.insn_store($var, &$func.insn_sub($var, $num));
    );
    ($func:ident, $var:ident *= $num:expr) => (
        $func.insn_store($var, &$func.insn_mul($var, $num));
    );
    ($func:ident, $var:ident /= $num:expr) => (
        $func.insn_store($var, &$func.insn_div($var, $num));
    );
    ($func:ident, $a:expr + $b:expr) => (
        $func.insn_add($a, $b)
    );
    ($func:ident, $a:expr - $b:expr) => (
        $func.insn_sub($a, $b)
    );
    ($func:ident, $a:expr * $b:expr) => (
        $func.insn_mul($a, $b)
    );
    ($func:ident, $a:expr / $b:expr) => (
        $func.insn_div($a, $b)
    );
    ($func:ident, $a:expr % $b:expr) => (
        $func.insn_rem($a, $b)
    );
    ($func:ident, $var:ident = $val:expr) => (
        $func.insn_store($var, $val);
    );
    ($func:ident, *$var:ident) => (
        $func.insn_load($var)
    );
    ($func:ident, call($call:expr,
        $($arg:expr),+
    )) => (
        $func.insn_call(None::<String>, $call, None, [$($arg),+].as_mut_slice())
    );
    ($func:ident, jump_table($value:expr,
        $($label:ident),+
    )) => (
    let ($($label),+) = {
        $(let $label:Label = Label::new($func);)+
        $func.insn_jump_table($value, [
            $($label),+
        ].as_mut_slice());
        ($($label),+)
    });
    ($func:expr, $value:expr) => (
        $func.insn_of(&$value)
    );
)<commit_msg>Only export public macros<commit_after>macro_rules! compile_prim(
    ($ty:ty, $type_name:ident, $make_constant:ident) => (
impl Compile for $ty {
    #[inline(always)]
    fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
        unsafe {
            NativeRef::from_ptr($make_constant(func.as_ptr(), $type_name, *self) )
        }
    }
    #[inline(always)]
    fn jit_type(_:Option<$ty>) -> Type {
        unsafe {
            NativeRef::from_ptr($type_name)
        }
    }
});
    ($ty:ty, $type_name:ident, $make_constant:ident, $cast:ty) => (
impl Compile for $ty {
    #[inline(always)]
    fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
        unsafe {
            NativeRef::from_ptr($make_constant(func.as_ptr(), $type_name, *self as $cast) )
        }
    }
    #[inline(always)]
    fn jit_type(_:Option<$ty>) -> Type {
        unsafe {
            NativeRef::from_ptr($type_name)
        }
    }
});
)

macro_rules! compile_func(
    (fn($($arg:ident),*) -> $ret:ty, $sig:ty) => (
    impl<$($arg:Compile,)* R:Compile> Compile for $sig {
        #[inline(always)]
        fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
            let ptr = (self as *const $sig).to_uint().compile(func);
            func.insn_convert(&ptr, get::<$sig>(), false)
        }
        #[inline(always)]
        fn jit_type(_:Option<$sig>) -> Type {
            Type::create_signature(CDECL, get::<R>(), [$(get::<$arg>()),*][mut])
        }
    })
)

macro_rules! compile_prims(
    ($(($ty:ty, $cast: ty) => ($type_name:ident, $make_constant:ident)),+) => (
        $(compile_prim!($ty, $type_name, $make_constant, $cast))+
    );
)

macro_rules! native_ref(
    ($name:ident, $field:ident, $pointer_ty:ty) => (
        #[allow(missing_copy_implementations)]
        #[deriving(PartialEq)]
        pub struct $name {
            $field: $pointer_ty
        }
        impl NativeRef for $name {
            #[inline(always)]
            /// Convert to a native pointer
            unsafe fn as_ptr(&self) -> $pointer_ty {
                self.$field
            }
            #[inline(always)]
            /// Convert from a native pointer
            unsafe fn from_ptr(ptr:$pointer_ty) -> $name {
                $name {
                    $field: ptr
                }
            }
        }
    );
    ($name:ident, $field:ident, $pointer_ty:ty, $lifetime:ident) => (
        #[deriving(PartialEq)]
        pub struct $name<'a> {
            $field: $pointer_ty,
            marker: $lifetime<'a>
        }
        impl<'a> NativeRef for $name<'a> {
            #[inline]
            /// Convert to a native pointer
            unsafe fn as_ptr(&self) -> $pointer_ty {
                self.$field
            }
            #[inline]
            /// Convert from a native pointer
            unsafe fn from_ptr<'a>(ptr:$pointer_ty) -> $name<'a> {
                $name {
                    $field: ptr,
                    marker: $lifetime::<'a>
                }
            }
        }
    )
)
#[macro_export]
macro_rules! jit(
    (struct {
        $($name:expr: $ty:ty),*
    }) => ({
        let structure = Type::create_struct([
            $(get::<$ty>()),*
        ].as_mut_slice());
        structure.set_names(&[$($name),*]);
        structure
    });
    (union {
        $($name:expr: $ty:ty),+
    }) => ({
        let structure = Type::create_union([
            $(get::<$ty>()),+
        ].as_mut_slice());
        structure.set_names(&[$($name),+]);
        structure
    });
    ($func:ident, return) => (
        $func.insn_default_return()
    );
    ($func:ident, return $($t:tt)+) => (
        $func.insn_return(jit!($($t)+))
    );
    ($func:ident, $var:ident += $num:expr) => (
        $func.insn_store($var, &$func.insn_add($var, $num));
    );
    ($func:ident, $var:ident -= $num:expr) => (
        $func.insn_store($var, &$func.insn_sub($var, $num));
    );
    ($func:ident, $var:ident *= $num:expr) => (
        $func.insn_store($var, &$func.insn_mul($var, $num));
    );
    ($func:ident, $var:ident /= $num:expr) => (
        $func.insn_store($var, &$func.insn_div($var, $num));
    );
    ($func:ident, $a:expr + $b:expr) => (
        $func.insn_add($a, $b)
    );
    ($func:ident, $a:expr - $b:expr) => (
        $func.insn_sub($a, $b)
    );
    ($func:ident, $a:expr * $b:expr) => (
        $func.insn_mul($a, $b)
    );
    ($func:ident, $a:expr / $b:expr) => (
        $func.insn_div($a, $b)
    );
    ($func:ident, $a:expr % $b:expr) => (
        $func.insn_rem($a, $b)
    );
    ($func:ident, $var:ident = $val:expr) => (
        $func.insn_store($var, $val);
    );
    ($func:ident, *$var:ident) => (
        $func.insn_load($var)
    );
    ($func:ident, call($call:expr,
        $($arg:expr),+
    )) => (
        $func.insn_call(None::<String>, $call, None, [$($arg),+].as_mut_slice())
    );
    ($func:ident, jump_table($value:expr,
        $($label:ident),+
    )) => (
    let ($($label),+) = {
        $(let $label:Label = Label::new($func);)+
        $func.insn_jump_table($value, [
            $($label),+
        ].as_mut_slice());
        ($($label),+)
    });
    ($func:expr, $value:expr) => (
        $func.insn_of(&$value)
    );
)<|endoftext|>