<commit_before>use read_token;
use range::Range;
use std::rc::Rc;

use {
    DebugId,
    ParseError,
    Node,
    Rule,
    Select,
    Token,
};

/// Stores information about whitespace.
pub struct Whitespace {
    /// Whether the whitespace is optional or required.
    pub optional: bool,
    /// A debug id to track down the rule generating an error.
    pub debug_id: DebugId,
}

impl Whitespace {
    /// Parse whitespace.
    /// If whitespace is required and no whitespace is found,
    /// an error will be reported.
    pub fn parse(&self, chars: &[char], offset: usize) ->
        Result<Range, (Range, ParseError)>
    {
        let range = read_token::whitespace(chars, offset);
        if range.length == 0 && !self.optional {
            Err((range, ParseError::ExpectedWhitespace(self.debug_id)))
        } else {
            Ok(range)
        }
    }

    /// Gets the rule for whitespace in the meta language.
    pub fn rule() -> Node {
        Node {
            debug_id: 0,
            name: Rc::new("whitespace".into()),
            body: vec![
                Rule::Whitespace(Whitespace { debug_id: 1, optional: true }),
                Rule::Token(Token {
                    debug_id: 2,
                    text: Rc::new("whitespace".into()),
                    inverted: false,
                    property: None
                }),
                Rule::Select(Select { debug_id: 3, args: vec![
                    Rule::Token(Token {
                        debug_id: 4,
                        text: Rc::new("?".into()),
                        inverted: false,
                        property: Some(Rc::new("optional".into())),
                    }),
                    Rule::Token(Token {
                        debug_id: 5,
                        text: Rc::new("!".into()),
                        inverted: true,
                        property: Some(Rc::new("optional".into())),
                    }),
                ]}),
            ],
        }
    }
}

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

    #[test]
    fn optional() {
        let text = "a,b, c";
        let chars: Vec<char> = text.chars().collect();
        let optional_whitespace = Whitespace { debug_id: 0, optional: true };
        assert_eq!(optional_whitespace.parse(&chars, 0),
            Ok(Range::new(0, 0)));
        assert_eq!(optional_whitespace.parse(&chars[4..], 4),
            Ok(Range::new(4, 1)));
    }

    #[test]
    fn required() {
        let text = "a,   b,c";
        let chars: Vec<char> = text.chars().collect();
        let required_whitespace = Whitespace { debug_id: 0, optional: false };
        assert_eq!(required_whitespace.parse(&chars[2..], 2),
            Ok(Range::new(2, 3)));
        // Prints an error message to standard error output.
        assert_eq!(required_whitespace.parse(&chars[7..], 7),
            Err((Range::new(7, 0), ParseError::ExpectedWhitespace(0))));
    }
}
<commit_msg>Removed unused meta rule for whitespace<commit_after>use read_token;
use range::Range;

use {
    DebugId,
    ParseError,
};

/// Stores information about whitespace.
pub struct Whitespace {
    /// Whether the whitespace is optional or required.
    pub optional: bool,
    /// A debug id to track down the rule generating an error.
    pub debug_id: DebugId,
}

impl Whitespace {
    /// Parse whitespace.
    /// If whitespace is required and no whitespace is found,
    /// an error will be reported.
    pub fn parse(&self, chars: &[char], offset: usize) ->
        Result<Range, (Range, ParseError)>
    {
        let range = read_token::whitespace(chars, offset);
        if range.length == 0 && !self.optional {
            Err((range, ParseError::ExpectedWhitespace(self.debug_id)))
        } else {
            Ok(range)
        }
    }
}

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

    #[test]
    fn optional() {
        let text = "a,b, c";
        let chars: Vec<char> = text.chars().collect();
        let optional_whitespace = Whitespace { debug_id: 0, optional: true };
        assert_eq!(optional_whitespace.parse(&chars, 0),
            Ok(Range::new(0, 0)));
        assert_eq!(optional_whitespace.parse(&chars[4..], 4),
            Ok(Range::new(4, 1)));
    }

    #[test]
    fn required() {
        let text = "a,   b,c";
        let chars: Vec<char> = text.chars().collect();
        let required_whitespace = Whitespace { debug_id: 0, optional: false };
        assert_eq!(required_whitespace.parse(&chars[2..], 2),
            Ok(Range::new(2, 3)));
        // Prints an error message to standard error output.
        assert_eq!(required_whitespace.parse(&chars[7..], 7),
            Err((Range::new(7, 0), ParseError::ExpectedWhitespace(0))));
    }
}
<|endoftext|>


<commit_before>extern crate polydraw;

use std::cmp::{Ordering, min, max};
use std::i64;

use polydraw::geom::point::Point;
use polydraw::{Application, Renderer, Frame};
use polydraw::raster::{Scene, Rasterizer, EdgeType, Poly, create_default_vec};

#[derive(Debug, Clone, Copy)]
pub struct Edge {
   pub edge_type: EdgeType,
   pub p1: Point,
   pub p2: Point,
}

impl Edge {
   #[inline]
   pub fn new(edge_type: EdgeType, x1: i64, y1: i64, x2: i64, y2: i64) -> Self {
      Edge {
         edge_type: edge_type,
         p1: Point::new(x1, y1),
         p2: Point::new(x2, y2),
      }
   }

   #[inline]
   pub fn vert_top(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LVT, x1, y1, x2, y2)
   }

   #[inline]
   pub fn vert_bottom(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LVB, x1, y1, x2, y2)
   }

   #[inline]
   pub fn hori_right(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LHR, x1, y1, x2, y2)
   }

   #[inline]
   pub fn hori_left(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LHL, x1, y1, x2, y2)
   }

   #[inline]
   pub fn top_right(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LTR, x1, y1, x2, y2)
   }

   #[inline]
   pub fn top_left(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LTL, x1, y1, x2, y2)
   }

   #[inline]
   pub fn bottom_right(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LBR, x1, y1, x2, y2)
   }

   #[inline]
   pub fn bottom_left(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LBL, x1, y1, x2, y2)
   }
}

#[derive(Debug, Clone, Copy, Default)]
pub struct Section {
   pub edge_type: EdgeType,
   pub p1: Point,
   pub p2: Point,
   pub edge: usize,
   pub poly: usize,
}

struct ClipRenderer {
   rasterizer: Rasterizer,
   div_per_pixel: i64,

   edges: Vec<Edge>,
   polys: Vec<Poly>,

   sections: Vec<Section>,
   sections_end: usize,

   sections_min_y: Vec<i64>,
   sections_max_y: Vec<i64>,
   sections_order: Vec<usize>,

   active: Vec<Section>,
   active_source: Vec<usize>,
   active_end: usize,
}

impl ClipRenderer {
   fn new() -> Self {
      let div_per_pixel = 1000;

      let mut edges = vec![
         Edge::top_left(5, 1, 1, 6),       // 0
         Edge::top_right(1, 6, 8, 9),      // 1
         Edge::bottom_right(8, 9, 9, 6),   // 2
         Edge::bottom_left(9, 6, 5, 1),    // 3
         Edge::top_right(1, 1, 3, 8),      // 4
         Edge::bottom_right(3, 8, 10, 4),  // 5
         Edge::bottom_left(10, 4, 1, 1),   // 6
      ];

      for edge in edges.iter_mut() {
         edge.p1.x *= div_per_pixel;
         edge.p1.y *= div_per_pixel;
         edge.p2.x *= div_per_pixel;
         edge.p2.y *= div_per_pixel;
      }

      let polys = vec![
         Poly::new(0, 4, 0),    // 0
         Poly::new(4, 7, 1),    // 1
      ];

      let sections = create_default_vec(65536);

      let sections_min_y = create_default_vec(65536);
      let sections_max_y = create_default_vec(65536);
      let sections_order = create_default_vec(65536);

      let active = create_default_vec(65536);
      let active_source = create_default_vec(65536);

      ClipRenderer {
         rasterizer: Rasterizer::new(),
         div_per_pixel: div_per_pixel,

         edges: edges,
         polys: polys,

         sections: sections,
         sections_end: 0,

         sections_min_y: sections_min_y,
         sections_max_y: sections_max_y,
         sections_order: sections_order,

         active: active,
         active_source: active_source,
         active_end: 0,
      }
   }

   fn create_scene(&self) -> Scene {
      let points = vec![];

      let segments = vec![];

      let circles = vec![];

      let edges = vec![];

      let polys = vec![];

      let colors = vec![];

      Scene {
         points: points,
         segments: segments,
         circles: circles,
         edges: edges,
         polys: polys,
         colors: colors,
      }
   }

   fn eval_sections_min_max_y(&mut self) {
      for section_index in 0..self.sections_end {
         let ref section = self.sections[section_index];

         let mut min_y = i64::MAX;
         let mut max_y = i64::MIN;

         let (section_min_y, section_max_y) = if section.edge_type.reversed() {
            (section.p2.y, section.p1.y)
         } else {
            (section.p1.y, section.p2.y)
         };

         if section_min_y < min_y  {
            min_y = section_min_y;
         }

         if section_max_y > max_y {
            max_y = section_max_y;
         }

         self.sections_min_y[section_index] = min_y;
         self.sections_max_y[section_index] = max_y;
         self.sections_order[section_index] = section_index;
      }

      self.sort_sections_order();

      println!("MIN Y {:?}", &self.sections_min_y[..self.sections_end]);
      println!("MAX Y {:?}", &self.sections_max_y[..self.sections_end]);
      println!("ORDER {:?}", &self.sections_order[..self.sections_end]);

      self.iterate_sections();
   }

   fn sort_sections_order(&mut self) {
      let sections_order = &mut self.sections_order[..self.sections_end];
      let sections_min_y = &self.sections_min_y;
      let sections_max_y = &self.sections_max_y;

      sections_order.sort_by(|a, b| {
         match sections_min_y[*a].cmp(&sections_min_y[*b]) {
            Ordering::Less => Ordering::Less,
            Ordering::Greater => Ordering::Greater,
            Ordering::Equal => sections_max_y[*a].cmp(&sections_max_y[*b])
         }
      });
   }

   fn iterate_sections(&self) {
      let mut prev_y = i64::MIN;
      for order_index in 0..self.sections_end {
         let section_index = self.sections_order[order_index];
         let min_y = self.sections_min_y[section_index];

         println!("I MIN Y {:?} {:?}", section_index, min_y);

         if min_y != prev_y {
            println!("HOR {:?}", min_y);
            prev_y = min_y;
         }
      }
   }

   fn transfer_sections(&mut self) {
      self.sections_end = 0;

      for poly_index in 0..self.polys.len() {
         let ref poly = self.polys[poly_index];

         for edge_index in poly.start..poly.end {
            let ref edge = self.edges[edge_index];

            self.sections[self.sections_end] = Section {
               edge_type: edge.edge_type,
               p1: edge.p1,
               p2: edge.p2,
               edge: edge_index,
               poly: poly_index,
            };

            self.sections_end += 1;
         }
      }

      println!("SECTIONS {:?}", &self.sections[..self.sections_end]);
   }

   fn clip_sections(&mut self) {
      let sections_taget = self.sections_order[0];
      let sections_clipper = self.sections_order[1];

      let active_target = self.copy_to_active(sections_taget);
      let active_clipper = self.copy_to_active(sections_clipper);

      let ref target = self.active[active_target];
      let ref clipper = self.active[active_clipper];

      println!("TARGET {:?}", target);
      println!("CLIPPER {:?}", clipper);

      let intersection = self.intersect_sections(target, clipper);
      println!("INTERSECTION {:?}", intersection);
   }

   fn copy_to_active(&mut self, sections_index: usize) -> usize {
      let active_index = self.active_end;

      self.active_source[active_index] = sections_index;
      self.active[active_index] = self.sections[sections_index];

      self.active_end += 1;

      active_index
   }

   fn intersect_sections(&self, s1: &Section, s2: &Section) -> Option<Point> {
      let s1_a = (s1.p2.y - s1.p1.y) as f64;
      let s1_b = (s1.p1.x - s1.p2.x) as f64;
      let s1_c = (s1.p2.x * s1.p1.y - s1.p1.x * s1.p2.y) as f64;

      let s2_a = (s2.p2.y - s2.p1.y) as f64;
      let s2_b = (s2.p1.x - s2.p2.x) as f64;
      let s2_c = (s2.p2.x * s2.p1.y - s2.p1.x * s2.p2.y) as f64;

      let denominator = s1_a * s2_b - s2_a * s1_b;

      if denominator == 0. {
         return None;
      }

      let x = (s2_c * s1_b - s1_c * s2_b) / denominator;
      let y = (s2_a * s1_c - s1_a * s2_c) / denominator;

      let x = x.round() as i64;
      let y = y.round() as i64;

      let x1 = max(min(s1.p1.x, s1.p2.x), min(s2.p1.x, s2.p2.x));
      let x2 = min(max(s1.p1.x, s1.p2.x), max(s2.p1.x, s2.p2.x));
      let y1 = max(min(s1.p1.y, s1.p2.y), min(s2.p1.y, s2.p2.y));
      let y2 = min(max(s1.p1.y, s1.p2.y), max(s2.p1.y, s2.p2.y));

      if x < x1 || x > x2 || y < y1 || y > y2 {
         return None;
      }

      return Some(Point::new(x, y));
   }
}

impl Renderer for ClipRenderer {
   fn render(&mut self, frame: &mut Frame) {
      frame.clear();

      self.transfer_sections();

      self.eval_sections_min_max_y();

      self.clip_sections();

      let scene = self.create_scene();

      self.rasterizer.render(&scene, frame, self.div_per_pixel);

      panic!("END");
   }
}

fn main() {
   let mut renderer = ClipRenderer::new();

   Application::new()
      .renderer(&mut renderer)
      .title("Clip")
      .run();
}
<commit_msg>Cutting the active and source intesecting sections from the top and bottom<commit_after>extern crate polydraw;

use std::cmp::{Ordering, min, max};
use std::i64;

use polydraw::geom::point::Point;
use polydraw::{Application, Renderer, Frame};
use polydraw::raster::{Scene, Rasterizer, EdgeType, Poly, create_default_vec};

#[derive(Debug, Clone, Copy)]
pub struct Edge {
   pub edge_type: EdgeType,
   pub p1: Point,
   pub p2: Point,
}

impl Edge {
   #[inline]
   pub fn new(edge_type: EdgeType, x1: i64, y1: i64, x2: i64, y2: i64) -> Self {
      Edge {
         edge_type: edge_type,
         p1: Point::new(x1, y1),
         p2: Point::new(x2, y2),
      }
   }

   #[inline]
   pub fn vert_top(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LVT, x1, y1, x2, y2)
   }

   #[inline]
   pub fn vert_bottom(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LVB, x1, y1, x2, y2)
   }

   #[inline]
   pub fn hori_right(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LHR, x1, y1, x2, y2)
   }

   #[inline]
   pub fn hori_left(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LHL, x1, y1, x2, y2)
   }

   #[inline]
   pub fn top_right(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LTR, x1, y1, x2, y2)
   }

   #[inline]
   pub fn top_left(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LTL, x1, y1, x2, y2)
   }

   #[inline]
   pub fn bottom_right(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LBR, x1, y1, x2, y2)
   }

   #[inline]
   pub fn bottom_left(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LBL, x1, y1, x2, y2)
   }
}

#[derive(Debug, Clone, Copy, Default)]
pub struct Section {
   pub edge_type: EdgeType,
   pub p1: Point,
   pub p2: Point,
   pub edge: usize,
   pub poly: usize,
}

impl Section {
   fn set_bottom(&mut self, point: &Point) {
      if self.edge_type.reversed() {
         self.p2 = *point;
      } else {
         self.p1 = *point;
      }
   }

   fn set_top(&mut self, point: &Point) {
      if self.edge_type.reversed() {
         self.p1 = *point;
      } else {
         self.p2 = *point;
      }
   }
}

struct ClipRenderer {
   rasterizer: Rasterizer,
   div_per_pixel: i64,

   edges: Vec<Edge>,
   polys: Vec<Poly>,

   sections: Vec<Section>,
   sections_end: usize,

   sections_min_y: Vec<i64>,
   sections_max_y: Vec<i64>,
   sections_order: Vec<usize>,

   active: Vec<Section>,
   active_source: Vec<usize>,
   active_end: usize,
}

impl ClipRenderer {
   fn new() -> Self {
      let div_per_pixel = 1000;

      let mut edges = vec![
         Edge::top_left(5, 1, 1, 6),       // 0
         Edge::top_right(1, 6, 8, 9),      // 1
         Edge::bottom_right(8, 9, 9, 6),   // 2
         Edge::bottom_left(9, 6, 5, 1),    // 3
         Edge::top_right(1, 1, 3, 8),      // 4
         Edge::bottom_right(3, 8, 10, 4),  // 5
         Edge::bottom_left(10, 4, 1, 1),   // 6
      ];

      for edge in edges.iter_mut() {
         edge.p1.x *= div_per_pixel;
         edge.p1.y *= div_per_pixel;
         edge.p2.x *= div_per_pixel;
         edge.p2.y *= div_per_pixel;
      }

      let polys = vec![
         Poly::new(0, 4, 0),    // 0
         Poly::new(4, 7, 1),    // 1
      ];

      let sections = create_default_vec(65536);

      let sections_min_y = create_default_vec(65536);
      let sections_max_y = create_default_vec(65536);
      let sections_order = create_default_vec(65536);

      let active = create_default_vec(65536);
      let active_source = create_default_vec(65536);

      ClipRenderer {
         rasterizer: Rasterizer::new(),
         div_per_pixel: div_per_pixel,

         edges: edges,
         polys: polys,

         sections: sections,
         sections_end: 0,

         sections_min_y: sections_min_y,
         sections_max_y: sections_max_y,
         sections_order: sections_order,

         active: active,
         active_source: active_source,
         active_end: 0,
      }
   }

   fn create_scene(&self) -> Scene {
      let points = vec![];

      let segments = vec![];

      let circles = vec![];

      let edges = vec![];

      let polys = vec![];

      let colors = vec![];

      Scene {
         points: points,
         segments: segments,
         circles: circles,
         edges: edges,
         polys: polys,
         colors: colors,
      }
   }

   fn eval_sections_min_max_y(&mut self) {
      for section_index in 0..self.sections_end {
         let ref section = self.sections[section_index];

         let mut min_y = i64::MAX;
         let mut max_y = i64::MIN;

         let (section_min_y, section_max_y) = if section.edge_type.reversed() {
            (section.p2.y, section.p1.y)
         } else {
            (section.p1.y, section.p2.y)
         };

         if section_min_y < min_y  {
            min_y = section_min_y;
         }

         if section_max_y > max_y {
            max_y = section_max_y;
         }

         self.sections_min_y[section_index] = min_y;
         self.sections_max_y[section_index] = max_y;
         self.sections_order[section_index] = section_index;
      }

      self.sort_sections_order();

      println!("MIN Y {:?}", &self.sections_min_y[..self.sections_end]);
      println!("MAX Y {:?}", &self.sections_max_y[..self.sections_end]);
      println!("ORDER {:?}", &self.sections_order[..self.sections_end]);

      self.iterate_sections();
   }

   fn sort_sections_order(&mut self) {
      let sections_order = &mut self.sections_order[..self.sections_end];
      let sections_min_y = &self.sections_min_y;
      let sections_max_y = &self.sections_max_y;

      sections_order.sort_by(|a, b| {
         match sections_min_y[*a].cmp(&sections_min_y[*b]) {
            Ordering::Less => Ordering::Less,
            Ordering::Greater => Ordering::Greater,
            Ordering::Equal => sections_max_y[*a].cmp(&sections_max_y[*b])
         }
      });
   }

   fn iterate_sections(&self) {
      let mut prev_y = i64::MIN;
      for order_index in 0..self.sections_end {
         let section_index = self.sections_order[order_index];
         let min_y = self.sections_min_y[section_index];

         println!("I MIN Y {:?} {:?}", section_index, min_y);

         if min_y != prev_y {
            println!("HOR {:?}", min_y);
            prev_y = min_y;
         }
      }
   }

   fn transfer_sections(&mut self) {
      self.sections_end = 0;

      for poly_index in 0..self.polys.len() {
         let ref poly = self.polys[poly_index];

         for edge_index in poly.start..poly.end {
            let ref edge = self.edges[edge_index];

            self.sections[self.sections_end] = Section {
               edge_type: edge.edge_type,
               p1: edge.p1,
               p2: edge.p2,
               edge: edge_index,
               poly: poly_index,
            };

            self.sections_end += 1;
         }
      }

      println!("SECTIONS {:?}", &self.sections[..self.sections_end]);
   }

   fn clip_sections(&mut self) {
      let sections_target = self.sections_order[0];
      let sections_clipper = self.sections_order[1];

      let active_target = self.copy_to_active(sections_target);
      let active_clipper = self.copy_to_active(sections_clipper);

      println!("TARGET {:?}", self.active[active_target]);
      println!("CLIPPER {:?}", self.active[active_clipper]);

      let intersection = self.intersect_sections(
         &self.active[active_target],
         &self.active[active_clipper]
      );
      println!("INTERSECTION {:?}", intersection);

      match intersection {
         Some(pt) => {
            self.sections[sections_target].set_bottom(&pt);
            self.sections[sections_clipper].set_bottom(&pt);

            self.active[active_target].set_top(&pt);
            self.active[active_clipper].set_top(&pt);
         },
         None => {}
      }

      for index in 0..self.sections_end {
         println!("SECTIONS [{}] - {:?}", index, self.sections[index]);
      }

      for index in 0..self.active_end {
         println!("ACTIVE   [{}] - {:?}", index, self.active[index]);
      }
   }

   fn copy_to_active(&mut self, sections_index: usize) -> usize {
      let active_index = self.active_end;

      self.active_source[active_index] = sections_index;
      self.active[active_index] = self.sections[sections_index];

      self.active_end += 1;

      active_index
   }

   fn intersect_sections(&self, s1: &Section, s2: &Section) -> Option<Point> {
      let s1_a = (s1.p2.y - s1.p1.y) as f64;
      let s1_b = (s1.p1.x - s1.p2.x) as f64;
      let s1_c = (s1.p2.x * s1.p1.y - s1.p1.x * s1.p2.y) as f64;

      let s2_a = (s2.p2.y - s2.p1.y) as f64;
      let s2_b = (s2.p1.x - s2.p2.x) as f64;
      let s2_c = (s2.p2.x * s2.p1.y - s2.p1.x * s2.p2.y) as f64;

      let denominator = s1_a * s2_b - s2_a * s1_b;

      if denominator == 0. {
         return None;
      }

      let x = (s2_c * s1_b - s1_c * s2_b) / denominator;
      let y = (s2_a * s1_c - s1_a * s2_c) / denominator;

      let x = x.round() as i64;
      let y = y.round() as i64;

      let x1 = max(min(s1.p1.x, s1.p2.x), min(s2.p1.x, s2.p2.x));
      let x2 = min(max(s1.p1.x, s1.p2.x), max(s2.p1.x, s2.p2.x));
      let y1 = max(min(s1.p1.y, s1.p2.y), min(s2.p1.y, s2.p2.y));
      let y2 = min(max(s1.p1.y, s1.p2.y), max(s2.p1.y, s2.p2.y));

      if x < x1 || x > x2 || y < y1 || y > y2 {
         return None;
      }

      return Some(Point::new(x, y));
   }
}

impl Renderer for ClipRenderer {
   fn render(&mut self, frame: &mut Frame) {
      frame.clear();

      self.transfer_sections();

      self.eval_sections_min_max_y();

      self.clip_sections();

      let scene = self.create_scene();

      self.rasterizer.render(&scene, frame, self.div_per_pixel);

      panic!("END");
   }
}

fn main() {
   let mut renderer = ClipRenderer::new();

   Application::new()
      .renderer(&mut renderer)
      .title("Clip")
      .run();
}
<|endoftext|>


<commit_before>#![cfg(feature = "alloc")]

extern crate nom;
extern crate jemallocator;

#[global_allocator]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

use nom::{
  branch::alt,
  bytes::complete::{escaped, tag, take_while},
  character::complete::{alphanumeric1 as alphanumeric, char, one_of},
  combinator::{map, opt, cut},
  error::{context, ErrorKind, ParseError},
  error::{VerboseError, VerboseErrorKind},
  multi::separated_list,
  number::complete::double,
  sequence::{delimited, preceded, separated_pair, terminated},
  Err, IResult, Offset,
};
use std::collections::HashMap;
use std::iter::repeat;
use std::str;

#[derive(Debug, PartialEq)]
pub enum JsonValue {
  Str(String),
  Boolean(bool),
  Num(f64),
  Array(Vec<JsonValue>),
  Object(HashMap<String, JsonValue>),
}

fn sp<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
  let chars = " \t\r\n";

  take_while(move |c| chars.contains(c))(i)
}

fn parse_str<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
  escaped(alphanumeric, '\\', one_of("\"n\\"))(i)
}

fn string<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
  context("string",
    preceded(
      char('\"'),
      cut(terminated(
          parse_str,
          char('\"')
  ))))(i)
}

fn boolean<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, bool, E> {
  alt((
      map(tag("false"), |_| false),
      map(tag("true"), |_| true)
  ))(input)
}

fn array<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, Vec<JsonValue>, E> {
  context(
    "array",
    preceded(char('['),
    cut(terminated(
      separated_list(preceded(sp, char(',')), value),
      preceded(sp, char(']'))))
  ))(i)
}

fn key_value<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, (&'a str, JsonValue), E> {
separated_pair(preceded(sp, string), cut(preceded(sp, char(':'))), value)(i)
}

fn hash<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, HashMap<String, JsonValue>, E> {
  context(
    "map",
    preceded(char('{'),
    cut(terminated(
      map(
        separated_list(preceded(sp, char(',')), key_value),
        |tuple_vec| {
          tuple_vec.into_iter().map(|(k, v)| (String::from(k), v)).collect()
      }),
      preceded(sp, char('}')),
    ))
  ))(i)
}

fn value<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, JsonValue, E> {
  preceded(
    sp,
    alt((
      map(hash, JsonValue::Object),
      map(array, JsonValue::Array),
      map(string, |s| JsonValue::Str(String::from(s))),
      map(double, JsonValue::Num),
      map(boolean, JsonValue::Boolean),
    )),
  )(i)
}

fn root<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, JsonValue, E> {
  delimited(
    sp,
    alt((map(hash, JsonValue::Object), map(array, JsonValue::Array))),
    opt(sp),
  )(i)
}

fn convert_error(input: &str, e: VerboseError<&str>) -> String {
  let lines: Vec<_> = input.lines().map(String::from).collect();

  let mut result = String::new();

  for (i, (substring, kind)) in e.errors.iter().enumerate() {
    let mut offset = input.offset(substring);

    let mut line = 0;
    let mut column = 0;

    for (j, l) in lines.iter().enumerate() {
      if offset <= l.len() {
        line = j;
        column = offset;
        break;
      } else {
        offset = offset - l.len() - 1;
      }

    }

    match kind {
      VerboseErrorKind::Char(c) => {
        result += &format!("{}: at line {}:\n", i, line);
        result += &lines[line];
        result += "\n";

        if column > 0 {
          result += &repeat(' ').take(column).collect::<String>();
        }
        result += "^\n";
        result += &format!("expected '{}', found {}\n\n", c, substring.chars().next().unwrap());
      }
      VerboseErrorKind::Context(s) => {
        result += &format!("{}: at line {}, in {}:\n", i, line, s);
        result += &lines[line];
        result += "\n";
        if column > 0 {
          result += &repeat(' ').take(column).collect::<String>();
        }
        result += "^\n\n";
      },
      /*VerboseErrorKind::Nom(e) => {
        result += &format!("{}: at line {}, in {:?}:\n", i, line, e);
        result += &lines[line];
        result += "\n";
        if column > 0 {
          result += &repeat(' ').take(column).collect::<String>();
        }
        result += "^\n\n";
      }*/
      _ => {}
    }
  }

  result
}

fn main() {
  let data = "  { \"a\"\t: 42,
  \"b\": [ \"x\", \"y\", 12 ] ,
  \"c\": { 1\"hello\" : \"world\"
  }
  } ";

  println!("will try to parse:\n\n**********\n{}\n**********\n", data);
  println!(
    "basic errors - `root::<(&str, ErrorKind)>(data)`:\n{:#?}\n",
    root::<(&str, ErrorKind)>(data)
  );
  println!("parsed verbose: {:#?}", root::<VerboseError<&str>>(data));

  match root::<VerboseError<&str>>(data) {
    Err(Err::Error(e)) | Err(Err::Failure(e)) => {
      println!("verbose errors - `root::<VerboseError>(data)`:\n{}", convert_error(data, e));
    }
    _ => panic!(),
  }
}
<commit_msg>add comments to the JSON example<commit_after>#![cfg(feature = "alloc")]

extern crate nom;
extern crate jemallocator;

#[global_allocator]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

use nom::{
  branch::alt,
  bytes::complete::{escaped, tag, take_while},
  character::complete::{alphanumeric1 as alphanumeric, char, one_of},
  combinator::{map, opt, cut},
  error::{context, convert_error, ErrorKind, ParseError,VerboseError},
  multi::separated_list,
  number::complete::double,
  sequence::{delimited, preceded, separated_pair, terminated},
  Err, IResult,
};
use std::collections::HashMap;
use std::str;

#[derive(Debug, PartialEq)]
pub enum JsonValue {
  Str(String),
  Boolean(bool),
  Num(f64),
  Array(Vec<JsonValue>),
  Object(HashMap<String, JsonValue>),
}

/// parser combinators are constructed from the bottom up:
/// first we write parsers for the smallest elements (here a space character),
/// then we'll combine them in larger parsers
fn sp<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
  let chars = " \t\r\n";

  // nom combinators like `take_while` return a function. That function is the
  // parser,to which we can pass the input
  take_while(move |c| chars.contains(c))(i)
}

/// A nom parser has the following signature:
/// `Input -> IResult<Input, Output, Error>`, with `IResult` defined as:
/// `type IResult<I, O, E = (I, ErrorKind)> = Result<(I, O), Err<E>>;`
///
/// most of the times you can ignore the error type and use the default (but this
/// examples shows custom error types later on!)
///
/// Here we use `&str` as input type, but nom parsers can be generic over
/// the input type, and work directly with `&[u8]` or any other type that
/// implements the required traits.
///
/// Finally, we can see here that the input and output type are both `&str`
/// with the same lifetime tag. This means that the produced value is a subslice
/// of the input data. and there is no allocation needed. This is the main idea
/// behind nom's performance.
fn parse_str<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
  escaped(alphanumeric, '\\', one_of("\"n\\"))(i)
}

/// `tag(string)` generates a parser that recognizes the argument string.
///
/// we can combine it with other functions, like `map` that takes the result
/// of another parser, and applies a function over it (`map` itself generates
/// a new parser`.
///
/// `alt` is another combinator that tries multiple parsers one by one, until
/// one of them succeeds
fn boolean<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, bool, E> {
  alt((
      map(tag("false"), |_| false),
      map(tag("true"), |_| true)
  ))(input)
}

/// this parser combines the previous `parse_str` parser, that recognizes the
/// interior of a string, with a parse to recognize the double quote character,
/// before the string (using `preceded`) and after the string (using `terminated`).
///
/// `context` and `cut` are related to error management:
/// - `cut` transforms an `Err::Error(e)` in `Err::Failure(e)`, signaling to
/// combinators like  `alt` that they should not try other parsers. We were in the
/// right branch (since we found the `"` character) but encountered an error when
/// parsing the string
/// - `context` lets you add a static string to provide more information in the
/// error chain (to indicate which parser had an error)
fn string<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
  context("string",
    preceded(
      char('\"'),
      cut(terminated(
          parse_str,
          char('\"')
  ))))(i)
}

/// some combinators, like `separated_list` or `many0`, will call a parser repeatedly,
/// accumulating results in a `Vec`, until it encounters an error.
/// If you want more control on the parser application, check out the `iterator`
/// combinator (cf `examples/iterator.rs`)
fn array<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, Vec<JsonValue>, E> {
  context(
    "array",
    preceded(char('['),
    cut(terminated(
      separated_list(preceded(sp, char(',')), value),
      preceded(sp, char(']'))))
  ))(i)
}

fn key_value<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, (&'a str, JsonValue), E> {
separated_pair(preceded(sp, string), cut(preceded(sp, char(':'))), value)(i)
}

fn hash<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, HashMap<String, JsonValue>, E> {
  context(
    "map",
    preceded(char('{'),
    cut(terminated(
      map(
        separated_list(preceded(sp, char(',')), key_value),
        |tuple_vec| {
          tuple_vec.into_iter().map(|(k, v)| (String::from(k), v)).collect()
      }),
      preceded(sp, char('}')),
    ))
  ))(i)
}

/// here, we apply the space parser before trying to parse a value
fn value<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, JsonValue, E> {
  preceded(
    sp,
    alt((
      map(hash, JsonValue::Object),
      map(array, JsonValue::Array),
      map(string, |s| JsonValue::Str(String::from(s))),
      map(double, JsonValue::Num),
      map(boolean, JsonValue::Boolean),
    )),
  )(i)
}

/// the root element of a JSON parser is either an object or an array
fn root<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, JsonValue, E> {
  delimited(
    sp,
    alt((map(hash, JsonValue::Object), map(array, JsonValue::Array))),
    opt(sp),
  )(i)
}

fn main() {
  let data = "  { \"a\"\t: 42,
  \"b\": [ \"x\", \"y\", 12 ] ,
  \"c\": { \"hello\" : \"world\"
  }
  } ";

  println!("will try to parse valid JSON data:\n\n**********\n{}\n**********\n", data);

  // this will print:
  // Ok(
  //     (
  //         "",
  //         Object(
  //             {
  //                 "b": Array(
  //                     [
  //                         Str(
  //                             "x",
  //                         ),
  //                         Str(
  //                             "y",
  //                         ),
  //                         Num(
  //                             12.0,
  //                         ),
  //                     ],
  //                 ),
  //                 "c": Object(
  //                     {
  //                         "hello": Str(
  //                             "world",
  //                         ),
  //                     },
  //                 ),
  //                 "a": Num(
  //                     42.0,
  //                 ),
  //             },
  //         ),
  //     ),
  // )
  println!(
    "parsing a valid file:\n{:#?}\n",
    root::<(&str, ErrorKind)>(data)
  );

  let data = "  { \"a\"\t: 42,
  \"b\": [ \"x\", \"y\", 12 ] ,
  \"c\": { 1\"hello\" : \"world\"
  }
  } ";

  println!("will try to parse invalid JSON data:\n\n**********\n{}\n**********\n", data);

  // here we use `(Input, ErrorKind)` as error type, which is used by default
  // if you don't specify it. It contains the position of the error and some
  // info on which parser encountered it.
  // It is fast and small, but does not provide much context.
  //
  // This will print:
  // basic errors - `root::<(&str, ErrorKind)>(data)`:
  // Err(
  //   Failure(
  //       (
  //           "1\"hello\" : \"world\"\n  }\n  } ",
  //           Char,
  //       ),
  //   ),
  // )
  println!(
    "basic errors - `root::<(&str, ErrorKind)>(data)`:\n{:#?}\n",
    root::<(&str, ErrorKind)>(data)
  );

  // nom also provides `the `VerboseError<Input>` type, which will generate a sort
  // of backtrace of the path through the parser, accumulating info on input positons
  // and affected parsers.
  //
  // This will print:
  //
  // parsed verbose: Err(
  //   Failure(
  //       VerboseError {
  //           errors: [
  //               (
  //                   "1\"hello\" : \"world\"\n  }\n  } ",
  //                   Char(
  //                       '}',
  //                   ),
  //               ),
  //               (
  //                   "{ 1\"hello\" : \"world\"\n  }\n  } ",
  //                   Context(
  //                       "map",
  //                   ),
  //               ),
  //               (
  //                   "{ \"a\"\t: 42,\n  \"b\": [ \"x\", \"y\", 12 ] ,\n  \"c\": { 1\"hello\" : \"world\"\n  }\n  } ",
  //                   Context(
  //                       "map",
  //                   ),
  //               ),
  //           ],
  //       },
  //   ),
  // )
  println!("parsed verbose: {:#?}", root::<VerboseError<&str>>(data));

  match root::<VerboseError<&str>>(data) {
    Err(Err::Error(e)) | Err(Err::Failure(e)) => {

      // here we use the `convert_error` function, to transform a `VerboseError<&str>`
      // into a printable trace.
      //
      // This will print:
      // verbose errors - `root::<VerboseError>(data)`:
      // 0: at line 2:
      //   "c": { 1"hello" : "world"
      //          ^
      // expected '}', found 1
      //
      // 1: at line 2, in map:
      //   "c": { 1"hello" : "world"
      //        ^
      //
      // 2: at line 0, in map:
      //   { "a" : 42,
      //   ^
      println!("verbose errors - `root::<VerboseError>(data)`:\n{}", convert_error(data, e));
    }
    _ => {},
  }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate ndarray;

use ndarray::prelude::*;
use ndarray::Array2;

const INPUT: &'static [u8] = include_bytes!("life.txt");
//const INPUT: &'static [u8] = include_bytes!("lifelite.txt");

const N: usize = 100;
//const N: usize = 8;

type Board = Array2<u8>;

fn parse(x: &[u8]) -> Board {
    // make a border of 0 cells
    let mut map = Board::from_elem(((N + 2) as Ix, (N + 2) as Ix), 0);
    let a = Array::from_iter(x.iter().filter_map(|&b| match b {
        b'#' => Some(1),
        b'.' => Some(0),
        _ => None,
    }));

    let a = a.into_shape((N as Ix, N as Ix)).unwrap();
    map.slice_mut(s![1..-1, 1..-1]).assign(&a);
    map
}

// Rules
//
// 2 or 3 neighbors: stay alive
// 3 neighbors: birth
// otherwise: death

fn iterate(z: &mut Board, scratch: &mut Board) {
    // compute number of neighbors
    let mut neigh = scratch.view_mut();
    neigh.assign_scalar(&0);
    neigh += &z.slice(s![0..-2, 0..-2]);
    neigh += &z.slice(s![0..-2, 1..-1]);
    neigh += &z.slice(s![0..-2, 2..  ]);

    neigh += &z.slice(s![1..-1, 0..-2]);
    neigh += &z.slice(s![1..-1, 2..  ]);

    neigh += &z.slice(s![2..  , 0..-2]);
    neigh += &z.slice(s![2..  , 1..-1]);
    neigh += &z.slice(s![2..  , 2..  ]);

    // birth where n = 3 and z[i] = 0,
    // survive where n = 2 || n = 3 and z[i] = 1
    let mut zv = z.slice_mut(s![1..-1, 1..-1]);

    // this is autovectorized amazingly well!
    zv.zip_mut_with(&neigh, |y, &n| {
        *y = ((n == 3) || (n == 2 && *y > 0)) as u8
    });
}

fn turn_on_corners(z: &mut Board) {
    let (n, m) = z.dim();
    z[[1    , 1    ]] = 1;
    z[[1    , m - 2]] = 1;
    z[[n - 2, 1    ]] = 1;
    z[[n - 2, m - 2]] = 1;
}

fn render(a: &Board) {
    for row in a.inner_iter() {
        for &x in row {
            if x > 0 {
                print!("#");
            } else {
                print!(".");
            }
        }
        println!("");
    }
}

fn main() {
    let mut a = parse(INPUT);
    let mut scratch = Board::zeros((N as Ix, N as Ix));
    let steps = 10000;
    turn_on_corners(&mut a);
    for _ in 0..steps {
        iterate(&mut a, &mut scratch);
        turn_on_corners(&mut a);
        //render(&a);
    }
    render(&a);
    let alive = a.iter().filter(|&&x| x > 0).count();
    println!("After {} steps there are {} cells alive", steps, alive);
}
<commit_msg>Fix life example to use 100 iterations again<commit_after>#[macro_use]
extern crate ndarray;

use ndarray::prelude::*;
use ndarray::Array2;

const INPUT: &'static [u8] = include_bytes!("life.txt");
//const INPUT: &'static [u8] = include_bytes!("lifelite.txt");

const N: usize = 100;
//const N: usize = 8;

type Board = Array2<u8>;

fn parse(x: &[u8]) -> Board {
    // make a border of 0 cells
    let mut map = Board::from_elem(((N + 2) as Ix, (N + 2) as Ix), 0);
    let a = Array::from_iter(x.iter().filter_map(|&b| match b {
        b'#' => Some(1),
        b'.' => Some(0),
        _ => None,
    }));

    let a = a.into_shape((N as Ix, N as Ix)).unwrap();
    map.slice_mut(s![1..-1, 1..-1]).assign(&a);
    map
}

// Rules
//
// 2 or 3 neighbors: stay alive
// 3 neighbors: birth
// otherwise: death

fn iterate(z: &mut Board, scratch: &mut Board) {
    // compute number of neighbors
    let mut neigh = scratch.view_mut();
    neigh.assign_scalar(&0);
    neigh += &z.slice(s![0..-2, 0..-2]);
    neigh += &z.slice(s![0..-2, 1..-1]);
    neigh += &z.slice(s![0..-2, 2..  ]);

    neigh += &z.slice(s![1..-1, 0..-2]);
    neigh += &z.slice(s![1..-1, 2..  ]);

    neigh += &z.slice(s![2..  , 0..-2]);
    neigh += &z.slice(s![2..  , 1..-1]);
    neigh += &z.slice(s![2..  , 2..  ]);

    // birth where n = 3 and z[i] = 0,
    // survive where n = 2 || n = 3 and z[i] = 1
    let mut zv = z.slice_mut(s![1..-1, 1..-1]);

    // this is autovectorized amazingly well!
    zv.zip_mut_with(&neigh, |y, &n| {
        *y = ((n == 3) || (n == 2 && *y > 0)) as u8
    });
}

fn turn_on_corners(z: &mut Board) {
    let (n, m) = z.dim();
    z[[1    , 1    ]] = 1;
    z[[1    , m - 2]] = 1;
    z[[n - 2, 1    ]] = 1;
    z[[n - 2, m - 2]] = 1;
}

fn render(a: &Board) {
    for row in a.inner_iter() {
        for &x in row {
            if x > 0 {
                print!("#");
            } else {
                print!(".");
            }
        }
        println!("");
    }
}

fn main() {
    let mut a = parse(INPUT);
    let mut scratch = Board::zeros((N as Ix, N as Ix));
    let steps = 100;
    turn_on_corners(&mut a);
    for _ in 0..steps {
        iterate(&mut a, &mut scratch);
        turn_on_corners(&mut a);
        //render(&a);
    }
    render(&a);
    let alive = a.iter().filter(|&&x| x > 0).count();
    println!("After {} steps there are {} cells alive", steps, alive);
}
<|endoftext|>


<commit_before>use std::fmt::Show;
use std::hash::{hash,Hash};
use std::collections::HashMap;
use std::thunk::Invoke;
use std::mem::replace;
//use std::sync::Arc;
use std::rc::Rc;

// "One big memo table" design

pub trait Adapton {
    fn new () -> Self ;

    // Names
    fn name_of_string (self:&mut Self, String) -> Name ;
    fn name_of_u64 (self:&mut Self, u64) -> Name ;
    fn name_pair (self: &Self, Name, Name) -> Name ;
    fn name_fork (self:&mut Self, Name) -> (Name, Name) ;

    fn ns<T,F> (self: &mut Self, Name, body:F) -> T
        where F:FnOnce(&mut Self) -> T ;

    fn put<T:Eq+Clone+Show> (self:&mut Self, T) -> Art<T> ;

    // Mutable cells
    fn cell<T:Eq+Clone+Show> (self:&mut Self, ArtId, T) -> MutArt<T> ;
    fn set<T:Eq+Clone+Show> (self:&mut Self, MutArt<T>, T) ;

    fn thunk<Arg:Eq+Hash+Clone+Show,T:Eq+Clone+Show>
        (self:&mut Self, id:ArtId,
         fn_body:Box<Invoke<Arg, T> + 'static>, arg:Arg) -> Art<T> ;

    fn force<T:Eq+Clone+Show> (self:&mut Self, Art<T>) -> T ;
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Lineage {
    Unknown, Structural,
    Root,
    Pair(Rc<Lineage>,Rc<Lineage>),
    ForkL(Rc<Lineage>),
    ForkR(Rc<Lineage>),
    String(String),
    U64(u64),
    Rc(Rc<Lineage>),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Path {
    Empty,
    Child(Rc<Path>,Name),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub struct Name {
    hash : u64,
    lineage : Rc<Lineage>,
}

#[derive(Hash,Show,PartialEq,Eq)]
pub struct Loc {
    hash : u64,
    name : Rc<Name>,
    path : Rc<Path>
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum ArtId {
    None,
    Structural(u64),
    Nominal(Name),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Art<T> {
    Box(Box<T>),
    Loc(Rc<Loc>),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum MutArt<T> {
    MutArt(Art<T>)
}

#[derive(Show)]
enum Node<T> {
    Pure(PureNode<T>),
    Mut(MutNode<T>),
    Compute(ComputeNode<T>),
}

#[derive(Show)]
struct PureNode<T> {
    loc : Rc<Loc>,
    val : T,
}

#[derive(Show)]
struct MutNode<T> {
    loc : Rc<Loc>,
    dem_precs : Vec<DemPrec>,
    val : T,
}

#[derive(Show)]
struct ComputeNode<T> {
    loc : Rc<Loc>,
    dem_precs : Vec<DemPrec>,
    dem_succs : Vec<DemSucc>,
    val  : Option<T>,
}

#[derive(Show)]
struct DemPrec {
    loc : Rc<Loc>,
}

#[derive(Show)]
struct DemSucc {
    loc : Rc<Loc>,
    dirty : bool
}

pub struct AdaptonState {
    memo_table : HashMap<Rc<Loc>, *mut ()>, // memo table
    curr_path : Rc<Path>, // current_namespace
    curr_name : Rc<Name>, // current articulation point
}

impl Adapton for AdaptonState {
    fn new () -> AdaptonState {
        let empty = Rc::new(Path::Empty);
        let root = Rc::new(Name{hash:0, lineage:Rc::new(Lineage::Root) });
        AdaptonState {
            memo_table : HashMap::new (),
            curr_path : empty,
            curr_name : root,
        }
    }
    fn name_of_string (self:&mut AdaptonState, sym:String) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::String(sym) ;
        Name{ hash:h, lineage:Rc::new(s) }
    }
    fn name_of_u64 (self:&mut AdaptonState, sym:u64) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::U64(sym) ;
        Name{ hash:h, lineage:Rc::new(s) }
    }
    fn name_pair (self: &AdaptonState, fst: Name, snd: Name) -> Name {
        let h = hash::<_>( &(fst.hash,snd.hash) ) ;
        let p = Lineage::Pair(fst.lineage, snd.lineage) ;
        Name{ hash:h, lineage:Rc::new(p) }
    }
    fn name_fork (self:&mut AdaptonState, nm:Name) -> (Name, Name) {
        let h1 = hash::<_>( &(&nm, 11111111) ) ; // TODO: make this hashing better.
        let h2 = hash::<_>( &(&nm, 22222222) ) ;
        ( Name{ hash:h1,
                lineage:Rc::new(Lineage::ForkL(nm.lineage.clone())) } ,
          Name{ hash:h2,
                lineage:Rc::new(Lineage::ForkR(nm.lineage)) } )
    }
    fn ns<T,F> (self: &mut Self, nm:Name, body:F) -> T where F:FnOnce(&mut Self) -> T {
        let path_body = Rc::new(Path::Child(self.curr_path.clone(), nm)) ;
        let path_pre = replace(&mut self.curr_path, path_body ) ;
        let x = body(self) ;
        let path_body = replace(&mut self.curr_path, path_pre) ;
        drop(path_body);
        x
    }
    fn put<T:Eq> (self:&mut AdaptonState, x:T) -> Art<T> {
        Art::Box(box x)
    }
    fn cell<T:Eq+Clone+Show> (self:&mut AdaptonState, id:ArtId, x:T) -> MutArt<T> {
        match id {
            ArtId::None => panic!(""),
            ArtId::Structural(hash) => {
                let loc = Loc{hash:hash,
                              name:Rc::new(Name{hash:hash,
                                                lineage:Rc::new(Lineage::Structural)}),
                              path:self.curr_path.clone()} ;
                MutArt::MutArt(Art::Loc(Rc::new(loc)))
            }
            ArtId::Nominal(nm) => {
                let loc = Loc{hash:nm.hash,
                              name:Rc::new(nm),
                              path:self.curr_path.clone()} ;
                MutArt::MutArt(Art::Loc(Rc::new(loc)))
            }
        }
    }
    fn set<T:Eq+Clone+Show> (self:&mut Self, cell:MutArt<T>, val:T) {
        match cell {
            MutArt::MutArt(Art::Box(b)) => {
                panic!("cannot set pure value");
            }
            MutArt::MutArt(Art::Loc(loc)) => {
                let node = self.memo_table.get(&loc) ;
                match node {
                    None => panic!("dangling pointer: {}", loc),
                    Some(ptr) => {
                        let node : &mut MutNode<T> = unsafe {
                            let node = std::mem::transmute::<*mut (), *mut Node<T>>(*ptr) ;
                            match *node {
                                Node::Mut(ref mut nd) => nd,
                                ref nd => panic!("impossible: {}", nd)
                            }} ;
                        if (node.val == val) {
                            // Nothing.
                        }
                        else {
                            node.val = val;
                            // TODO: Dirty traversal. Notify/mark demand precs.
                        }
                    }
                }
            }
        }
    }
    fn thunk<Arg:Eq+Hash+Clone+Show,T:Eq+Clone+Show>
        (self:&mut AdaptonState,
         id:ArtId, fn_body:Box<Invoke<Arg,T>+'static>, arg:Arg) -> Art<T>
    {
        panic!("")
    }
    fn force<T:Eq+Clone+Show> (self:&mut AdaptonState, art:Art<T>) -> T {
        match art {
            Art::Box(b) => *b,
            Art::Loc(loc) => {
                let node = self.memo_table.get(&loc) ;
                match node {
                    None => panic!("dangling pointer: {}", loc),
                    Some(ptr) => {
                        let node : &mut Node<T> = unsafe {
                            let node = std::mem::transmute::<*mut (), *mut Node<T>>(*ptr) ;
                            &mut ( *node ) } ;
                        match *node {
                            Node::Pure(ref mut nd) => {
                                nd.val.clone()
                            }
                            Node::Mut(ref mut nd) => {
                                // TODO: Record dependency edge
                                nd.val.clone()
                            }
                            Node::Compute(ref mut nd) => {
                                panic!("TODO")
                            }
                        }
                    }
                }
            }
        }
    }
}

pub fn main () {

}
<commit_msg>implemented set and force for mutable cells<commit_after>use std::fmt::Show;
use std::hash::{hash,Hash};
use std::collections::HashMap;
use std::thunk::Invoke;
use std::mem::replace;
//use std::sync::Arc;
use std::rc::Rc;

// "One big memo table" design

pub trait Adapton {
    fn new () -> Self ;

    // Names
    fn name_of_string (self:&mut Self, String) -> Name ;
    fn name_of_u64 (self:&mut Self, u64) -> Name ;
    fn name_pair (self: &Self, Name, Name) -> Name ;
    fn name_fork (self:&mut Self, Name) -> (Name, Name) ;

    fn ns<T,F> (self: &mut Self, Name, body:F) -> T
        where F:FnOnce(&mut Self) -> T ;

    fn put<T:Eq+Clone+Show> (self:&mut Self, T) -> Art<T> ;

    // Mutable cells
    fn cell<T:Eq+Clone+Show> (self:&mut Self, ArtId, T) -> MutArt<T> ;
    fn set<T:Eq+Clone+Show> (self:&mut Self, MutArt<T>, T) ;

    fn thunk<Arg:Eq+Hash+Clone+Show,T:Eq+Clone+Show>
        (self:&mut Self, id:ArtId,
         fn_body:Box<Invoke<Arg, T> + 'static>, arg:Arg) -> Art<T> ;

    fn force<T:Eq+Clone+Show> (self:&mut Self, Art<T>) -> T ;
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Lineage {
    Unknown, Structural,
    Root,
    Pair(Rc<Lineage>,Rc<Lineage>),
    ForkL(Rc<Lineage>),
    ForkR(Rc<Lineage>),
    String(String),
    U64(u64),
    Rc(Rc<Lineage>),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Path {
    Empty,
    Child(Rc<Path>,Name),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub struct Name {
    hash : u64,
    lineage : Rc<Lineage>,
}

#[derive(Hash,Show,PartialEq,Eq)]
pub struct Loc {
    hash : u64,
    name : Rc<Name>,
    path : Rc<Path>
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum ArtId {
    None,
    Structural(u64),
    Nominal(Name),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Art<T> {
    Box(Box<T>),
    Loc(Rc<Loc>),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum MutArt<T> {
    MutArt(Art<T>)
}

#[derive(Show)]
enum Node<T> {
    Pure(PureNode<T>),
    Mut(MutNode<T>),
    Compute(ComputeNode<T>),
}

#[derive(Show)]
struct PureNode<T> {
    loc : Rc<Loc>,
    val : T,
}

#[derive(Show)]
struct MutNode<T> {
    loc : Rc<Loc>,
    creators  : Vec<DemPrec>,
    dem_precs : Vec<DemPrec>,
    val : T,
}

#[derive(Show)]
struct ComputeNode<T> {
    loc : Rc<Loc>,
    creators  : Vec<DemPrec>,
    dem_precs : Vec<DemPrec>,
    dem_succs : Vec<DemSucc>,
    val  : Option<T>,
}

#[derive(Show)]
struct DemPrec {
    loc : Rc<Loc>,
}

#[derive(Show)]
struct DemSucc {
    loc : Rc<Loc>,
    dirty : bool
}

pub struct AdaptonState {
    memo_table : HashMap<Rc<Loc>, *mut ()>, // memo table
    curr_path : Rc<Path>, // current_namespace
    curr_name : Rc<Name>, // current articulation point
}

impl Adapton for AdaptonState {

    fn new () -> AdaptonState {
        let empty = Rc::new(Path::Empty);
        let root = Rc::new(Name{hash:0, lineage:Rc::new(Lineage::Root) });
        AdaptonState {
            memo_table : HashMap::new (),
            curr_path : empty,
            curr_name : root,
        }
    }

    fn name_of_string (self:&mut AdaptonState, sym:String) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::String(sym) ;
        Name{ hash:h, lineage:Rc::new(s) }
    }

    fn name_of_u64 (self:&mut AdaptonState, sym:u64) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::U64(sym) ;
        Name{ hash:h, lineage:Rc::new(s) }
    }

    fn name_pair (self: &AdaptonState, fst: Name, snd: Name) -> Name {
        let h = hash::<_>( &(fst.hash,snd.hash) ) ;
        let p = Lineage::Pair(fst.lineage, snd.lineage) ;
        Name{ hash:h, lineage:Rc::new(p) }
    }

    fn name_fork (self:&mut AdaptonState, nm:Name) -> (Name, Name) {
        let h1 = hash::<_>( &(&nm, 11111111) ) ; // TODO: make this hashing better.
        let h2 = hash::<_>( &(&nm, 22222222) ) ;
        ( Name{ hash:h1,
                lineage:Rc::new(Lineage::ForkL(nm.lineage.clone())) } ,
          Name{ hash:h2,
                lineage:Rc::new(Lineage::ForkR(nm.lineage)) } )
    }

    fn ns<T,F> (self: &mut Self, nm:Name, body:F) -> T where F:FnOnce(&mut Self) -> T {
        let path_body = Rc::new(Path::Child(self.curr_path.clone(), nm)) ;
        let path_pre = replace(&mut self.curr_path, path_body ) ;
        let x = body(self) ;
        let path_body = replace(&mut self.curr_path, path_pre) ;
        drop(path_body);
        x
    }

    fn put<T:Eq> (self:&mut AdaptonState, x:T) -> Art<T> {
        Art::Box(box x)
    }

    fn cell<T:Eq+Clone+Show> (self:&mut AdaptonState, id:ArtId, val:T) -> MutArt<T> {
        let loc = match id {
            ArtId::None => panic!(""),
            ArtId::Structural(hash) => {
                Rc::new(Loc{
                    hash:hash,
                    name:Rc::new(Name{hash:hash,
                                      lineage:Rc::new(Lineage::Structural)}),
                    path:self.curr_path.clone()
                })
            }
            ArtId::Nominal(nm) => {
                Rc::new(Loc{
                    hash:nm.hash,
                    name:Rc::new(nm),
                    path:self.curr_path.clone() })
            }} ;
        let mut node = Node::Mut(MutNode{
            loc:loc.clone(),
            dem_precs:Vec::new(),
            creators:Vec::new(),
            val:val
        }) ;
        let ptr = unsafe { std::mem::transmute::<*mut Node<T>,*mut ()>(&mut node) } ;
        self.memo_table.insert(loc.clone(), ptr) ;
        MutArt::MutArt(Art::Loc(loc))
    }

    fn set<T:Eq+Clone+Show> (self:&mut Self, cell:MutArt<T>, val:T) {
        match cell {
            MutArt::MutArt(Art::Box(b)) => {
                panic!("cannot set pure value");
            }
            MutArt::MutArt(Art::Loc(loc)) => {
                let node = self.memo_table.get(&loc) ;
                match node {
                    None => panic!("dangling pointer: {}", loc),
                    Some(ptr) => {
                        let node : &mut MutNode<T> = unsafe {
                            let node = std::mem::transmute::<*mut (), *mut Node<T>>(*ptr) ;
                            match *node {
                                Node::Mut(ref mut nd) => nd,
                                ref nd => panic!("impossible: {}", nd)
                            }} ;
                        if (node.val == val) {
                            // Nothing.
                        }
                        else {
                            node.val = val;
                            // TODO: Dirty traversal. Notify/mark demand precs.
                        }
                    }
                }
            }
        }
    }

    fn thunk<Arg:Eq+Hash+Clone+Show,T:Eq+Clone+Show>
        (self:&mut AdaptonState,
         id:ArtId, fn_body:Box<Invoke<Arg,T>+'static>, arg:Arg) -> Art<T>
    {
        panic!("")
    }

    fn force<T:Eq+Clone+Show> (self:&mut AdaptonState, art:Art<T>) -> T {
        match art {
            Art::Box(b) => *b,
            Art::Loc(loc) => {
                let node = self.memo_table.get(&loc) ;
                match node {
                    None => panic!("dangling pointer: {}", loc),
                    Some(ptr) => {
                        let node : &mut Node<T> = unsafe {
                            let node = std::mem::transmute::<*mut (), *mut Node<T>>(*ptr) ;
                            &mut ( *node ) } ;
                        match *node {
                            Node::Pure(ref mut nd) => {
                                nd.val.clone()
                            }
                            Node::Mut(ref mut nd) => {
                                // TODO: Record dependency edge
                                nd.val.clone()
                            }
                            Node::Compute(ref mut nd) => {
                                panic!("TODO")
                            }
                        }
                    }
                }
            }
        }
    }

}

pub fn main () {

}
<|endoftext|>


<commit_before>extern crate turtle;

use turtle::*;

fn draw(turtle: &mut Turtle, side: f64, deep: usize) {
    let next_side = side / f64::sqrt(2.0);

    for _ in 0..4 {
        let position = turtle.position();
        turtle.set_pen_color(get_color(position));
        turtle.right(90.0);
        turtle.forward(side);
    }

    if deep > 0 {
        turtle.pen_up();
        turtle.left(45.0);
        turtle.forward(next_side);
        let position = turtle.position();
        turtle.pen_down();

        let heading = turtle.heading();

        draw(turtle, next_side, deep - 1);
        turtle.set_heading(heading);

        turtle.pen_up();
        turtle.go_to(position);
        turtle.right(135.0);
        turtle.forward(side);
        turtle.left(45.0);
        turtle.forward(next_side);
        turtle.pen_down();

        let heading = turtle.heading();

        draw(turtle, next_side, deep - 1);
        turtle.set_heading(heading);
    }
}

fn get_color(position: [f64;2]) -> Color {
    Color{
        red: 130.0 + f64::abs(position[0] % 75.0),
        green: 150.0 + f64::abs(position[1] % 55.0),
        blue: 210.0 + f64::abs(position[1] % 25.0),
        alpha: 0.8
    }
}

fn main() {
    let mut turtle = Turtle::new();
    turtle.set_speed(Speed::Ten);
    let side = 100.0;

    turtle.pen_up();
    turtle.backward(1.5 * side);
    turtle.pen_down();

    draw(&mut turtle, side, 6);
}
<commit_msg>Update tree.rs<commit_after>//! Draw a fractal tree.
//! (https://www.youtube.com/watch?v=9UtdjVWSluo)

extern crate turtle;

use turtle::{Turtle, Point, Color};

/// Draw the tree. It's a fractal which consists of 1 large square and 2 small squares.
///
/// `side`: The side of the large square.
/// `depth`: The quantity of the levels of the tree.
fn draw(turtle: &mut Turtle, side: f64, depth: usize) {
    // Draw the large square
    for _ in 0..4 {
        // Get position for setting color
        let position = turtle.position();
        // Each side has a different color
        turtle.set_pen_color(get_color(position));

        turtle.right(90.0);
        turtle.forward(side);
    }

    // If you need to draw a smaller level
    if depth > 0 {
        // The side of the small square
        let smaller_side = side / f64::sqrt(2.0);

        // Move to the starting position of the left small square
        turtle.pen_up();
        turtle.left(45.0);
        turtle.forward(smaller_side);
        let position = turtle.position();
        turtle.pen_down();

        // Remember the heading
        let heading = turtle.heading();

        // Draw the left small square
        // It's the large square on the next level/depth
        draw(turtle, smaller_side, depth - 1);

        // Restore the heading
        turtle.set_heading(heading);

        // Return to the starting position of the left small square
        // Move to the starting position of the right small square
        turtle.pen_up();
        turtle.go_to(position);
        turtle.right(135.0);
        turtle.forward(side);
        turtle.left(45.0);
        turtle.forward(smaller_side);
        turtle.pen_down();

        // Draw the right small square
        // It's the large square on the next level/depth
        draw(turtle, smaller_side, depth - 1);
    }
}

/// Returns the color by the position of the turtle
fn get_color(position: Point) -> Color {
    Color {
        red: 130.0 + f64::abs(position[0] % 75.0),
        green: 150.0 + f64::abs(position[1] % 55.0),
        blue: 210.0 + f64::abs(position[1] % 25.0),
        alpha: 0.8
    }
}

fn main() {
    let mut turtle = Turtle::new();
    turtle.set_speed(10);

    // The side of the first large square
    let side = 100.0;

    // Move to the bottom of the window
    // The tree is growing up, it needs a place above
    turtle.pen_up();
    turtle.backward(1.5 * side);
    turtle.pen_down();

    // Draw the tree
    draw(&mut turtle, side, 6);
}
<|endoftext|>


<commit_before>struct Point { x: i32, y: i32, z: i32 }

fn main() {
    let mut point = Point { x: 0, y: 0, z: 0 };

    {
        let borrowed_point = &point;
        let another_borrow = &point;

        // 通过引用和原始所有者来访问数据
        println!("Point has coordinates: ({}, {}, {})",
                 borrowed_point.x, another_borrow.y, point.z);

        // 报错！不能借用 `point` 作为可变内容，因为目前已被借用成为
        // 不可变内容。
        //let mutable_borrow = &mut point;
        // 动手试一试 ^ 将此行注释去掉。

        // 不可变引用离开作用域
    }

    {
        let mutable_borrow = &mut point;

        // 通过可变引用来改变数据
        mutable_borrow.x = 5;
        mutable_borrow.y = 2;
        mutable_borrow.z = 1;

        // 报错！不能借用 `point` 作为不可变内容，因为目前它已被借用成为
        // 可变内容。
        //let y = &point.y;
        // 动手试一试 ^ 将此行注释去掉。

        // 报错！不能打印，因为 `println!` 接受了一个不可变引用。
        //println!("Point Z coordinate is {}", point.z);
        // 动手试一试 ^ 将此行注释去掉。

        // 好！可变引用可以作为不可变的传给 `println!`。
        println!("Point has coordinates: ({}, {}, {})",
                 mutable_borrow.x, mutable_borrow.y, mutable_borrow.z);

        // 可变引用离开作用域
    }

    // `point` 的不可变引用再次可用。
    let borrow_point = &point;
    println!("Point now has coordinates: ({}, {}, {})",
             borrowed_point.x, borrowed_point.y, borrowed_point.z);
}
<commit_msg>Typo fix<commit_after>struct Point { x: i32, y: i32, z: i32 }

fn main() {
    let mut point = Point { x: 0, y: 0, z: 0 };

    {
        let borrowed_point = &point;
        let another_borrow = &point;

        // 通过引用和原始所有者来访问数据
        println!("Point has coordinates: ({}, {}, {})",
                 borrowed_point.x, another_borrow.y, point.z);

        // 报错！不能借用 `point` 作为可变内容，因为目前已被借用成为
        // 不可变内容。
        //let mutable_borrow = &mut point;
        // 动手试一试 ^ 将此行注释去掉。

        // 不可变引用离开作用域
    }

    {
        let mutable_borrow = &mut point;

        // 通过可变引用来改变数据
        mutable_borrow.x = 5;
        mutable_borrow.y = 2;
        mutable_borrow.z = 1;

        // 报错！不能借用 `point` 作为不可变内容，因为目前它已被借用成为
        // 可变内容。
        //let y = &point.y;
        // 动手试一试 ^ 将此行注释去掉。

        // 报错！不能打印，因为 `println!` 接受了一个不可变引用。
        //println!("Point Z coordinate is {}", point.z);
        // 动手试一试 ^ 将此行注释去掉。

        // 好！可变引用可以作为不可变的传给 `println!`。
        println!("Point has coordinates: ({}, {}, {})",
                 mutable_borrow.x, mutable_borrow.y, mutable_borrow.z);

        // 可变引用离开作用域
    }

    // `point` 的不可变引用再次可用。
    let borrowed_point = &point;
    println!("Point now has coordinates: ({}, {}, {})",
             borrowed_point.x, borrowed_point.y, borrowed_point.z);
}
<|endoftext|>


<commit_before>//
// zhtta.rs
//
// Running on Rust 0.8
//
// Starting code for PS3
//
// Note: it would be very unwise to run this server on a machine that is
// on the Internet and contains any sensitive files!
//
// University of Virginia - cs4414 Fall 2013
// Weilin Xu and David Evans
// Version 0.3

extern mod extra;

use std::rt::io::*;
use std::rt::io::net::ip::SocketAddr;
use std::io::println;
use std::cell::Cell;
use std::{os, str, io};
use extra::arc;
use extra::time;
use std::comm::*;
use std::hashmap::HashMap;

use std::rt::io::net::tcp::TcpStream;

static PORT: int = 4414;
static IP: &'static str = "127.0.0.1";

struct sched_msg {
    stream: Option<std::rt::io::net::tcp::TcpStream>,
    filepath: ~std::path::PosixPath
}

// determine if the request is from a Charlottesville client

fn is_Wahoo_Client(peer_addr: ~str) ->bool
{
	let WahooIPs: ~[~str] = ~[~"128.143.", ~"137.54."]; // probably add some more ip addresses on the way
	let mut isWahoo = false;
	let mut index = 0;

	while index < WahooIPs.len()
	{
		if peer_addr.starts_with(WahooIPs[index])
		{
			isWahoo = true;
			break;
		}
		index += 1;
	}
	//println( fmt!("is wahoo? : %?\n", isWahoo) );
	return isWahoo;
}

// get the size of a file

fn get_fileSize(file_path: &Path) -> int
{
	let mut filestream = std::rt::io::file::open(file_path, Open, Read);
	let mut size:int = 0;

	// find the File size
	match filestream{
		Some(ref mut reader) =>
		{
			reader.seek(0,SeekEnd);
			size = reader.tell() as int;
			reader.seek(0, SeekSet); // rewind the file back

			println(fmt!("\nfile size: %? bytes \n", size ));
		},
		None => { fail!("\nCannot read the storage file \n");},
	}
	return size;
}

fn main() {

    let visitor_count: uint = 0; // @@@@@@@

    let mut isWahoo: bool = false;

    let req_vec: ~[sched_msg] = ~[];
    let shared_req_vec = arc::RWArc::new(req_vec);
    let add_vec = shared_req_vec.clone();
    let take_vec = shared_req_vec.clone();

    let (port, chan) = stream();
    let chan = SharedChan::new(chan);

    // dequeue file requests, and send responses.
    // FIFO
    do spawn {
        let (sm_port, sm_chan) = stream();

        // a task for sending responses.
        do spawn {
	    let mut cache: HashMap<~str, ~[u8]> = std::hashmap::HashMap::new();
	    let mut cacheTimes: HashMap<~str, ~i64> = std::hashmap::HashMap::new();
            loop {
                let mut tf: sched_msg = sm_port.recv(); // wait for the dequeued request to handle
		let modifiedTime = match file::stat(tf.filepath) {
			Some(s) => {
					s.modified
				   }
			None => {
					-1
				}
		};
		if cache.contains_key_equiv(&tf.filepath.to_str()) &&
				*cacheTimes.get_copy(&tf.filepath.to_str()) as u64 > modifiedTime {
			println(fmt!("begin serving file [%?]", tf.filepath));
                        // A web server should always reply a HTTP header for any legal HTTP request.
                        tf.stream.write("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n".as_bytes());
			let data = cache.get_copy(&tf.filepath.to_str());
                        tf.stream.write(data);
                        println(fmt!("finish file [%?]", tf.filepath));
		}
		else {
		     let file = io::read_whole_file(tf.filepath);
   	             match file { // killed if file size is larger than memory size.
                	    Ok(file_data) => {
                 	       println(fmt!("begin serving file [%?]", tf.filepath));
                 	       // A web server should always reply a HTTP header for any legal HTTP request.
                 	       tf.stream.write("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n".as_bytes());
                        	tf.stream.write(file_data);
                        	println(fmt!("finish file [%?]", tf.filepath));
				cache.insert(tf.filepath.to_str(), file_data);
				cacheTimes.insert(tf.filepath.to_str(), ~time::get_time().sec);
                    	    }
                    	    Err(err) => {
                        	println(err);
                    	    }
                    }
		}
            }
        }

        loop {
            port.recv(); // wait for arrving notification
            do take_vec.write |vec| {
                if ((*vec).len() > 0) {
                    // LIFO didn't make sense in service scheduling, so we modify it as FIFO by using shift_opt() rather than pop().
                    let tf_opt: Option<sched_msg> = (*vec).shift_opt();
                    let tf = tf_opt.unwrap();
                    println(fmt!("shift from queue, size: %ud", (*vec).len()));
                    sm_chan.send(tf); // send the request to send-response-task to serve.
                }
            }
        }
    }

    let ip = match FromStr::from_str(IP) { Some(ip) => ip,
					   None     => {println(fmt!("Error: Invalid IP address <%s>", IP));
						        return;}
 					 };

    let socket = net::tcp::TcpListener::bind(SocketAddr {ip: ip, port: PORT as u16});

    println(fmt!("Listening on %s:%d ...", ip.to_str(), PORT));
    let mut acceptor = socket.listen().unwrap();

    let shared_count = arc::RWArc::new( visitor_count ); // @@@@@@

    for stream in acceptor.incoming() {
	let mut stream = stream; // @@@@@@
	let mut peer_addr: ~str = ~"";

	match stream {
		Some(ref mut s) =>
		{
			match s.peer_name() {
				Some(pn) =>
				{ 	peer_addr = pn.to_str();
					println( fmt!("\nPeer address: %s", peer_addr ));
				},
				None 	 => ()
			}
		}
		None => ()
	} 			// @@@@@

	isWahoo = is_Wahoo_Client(peer_addr);
	println( fmt!("is wahoo? : %?\n", isWahoo) );

	let stream = Cell::new(stream);

	let (count_port, count_chan): (Port< extra::arc::RWArc<uint> >, Chan< extra::arc::RWArc<uint> >) = std::comm::stream(); // @@@@@@
        let count_chan = SharedChan::new(count_chan); // @@@@@@
        count_chan.send(shared_count.clone() ); // @@@@@@

        // Start a new task to handle the connection
        let child_chan = chan.clone();
	let child_add_vec = add_vec.clone();

        do spawn {

	    let shared_count_copy = count_port.recv(); // @@@@@@

	    /* Get Write Access */
	    do shared_count_copy.write |count|{
			*count = *count + 1;
			println( fmt!("count: %? \n", *count as int) );
    	    }

            let mut stream = stream.take();
            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);

            let req_group : ~[&str]= request_str.splitn_iter(' ', 3).collect();
            if req_group.len() > 2 {
                let path = req_group[1];
                println(fmt!("Request for path: \n%?", path));

                let file_path = ~os::getcwd().push(path.replace("/../", ""));

                if !os::path_exists(file_path) || os::path_is_dir(file_path)
		{
                    println(fmt!("Request received:\n%s", request_str));

		    /* Get Read Access */
		    do shared_count_copy.read |count|
		    {
   			let response: ~str = fmt!(
                        "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
			<doctype !html>
			<title>Hello, Rust!</title>

Greetings, Krusty!

Visitor count: %u

			\r\n", *count);

			stream.write(response.as_bytes());
    	    	    }

                }
                else {
                    // Requests scheduling

		    let size:int = get_fileSize(file_path); // @@@@@@@@@@@

                    let msg: sched_msg = sched_msg{stream: stream, filepath: file_path.clone()};
                    let (sm_port, sm_chan) = std::comm::stream();
                    sm_chan.send(msg);

                    do child_add_vec.write |vec| {
                        let msg = sm_port.recv();
                        (*vec).push(msg); // enqueue new request.
                        println("add to queue");
                    }
                    child_chan.send(""); //notify the new arriving request.

                    println(fmt!("get file request: %?", file_path));
                }
            }
            println!("connection terminates\n")
        }
    }
}

<commit_msg>Added code to prevent multiple files from entering the channel to the serving thread at the same time.<commit_after>//
// zhtta.rs
//
// Running on Rust 0.8
//
// Starting code for PS3
//
// Note: it would be very unwise to run this server on a machine that is
// on the Internet and contains any sensitive files!
//
// University of Virginia - cs4414 Fall 2013
// Weilin Xu and David Evans
// Version 0.3

extern mod extra;

use std::rt::io::*;
use std::rt::io::net::ip::SocketAddr;
use std::io::println;
use std::cell::Cell;
use std::{os, str, io};
use extra::arc;
use extra::time;
use std::comm::*;
use std::hashmap::HashMap;

use std::rt::io::net::tcp::TcpStream;

static PORT: int = 4414;
static IP: &'static str = "127.0.0.1";

struct sched_msg {
    stream: Option<std::rt::io::net::tcp::TcpStream>,
    filepath: ~std::path::PosixPath
}

// determine if the request is from a Charlottesville client

fn is_Wahoo_Client(peer_addr: ~str) ->bool
{
	let WahooIPs: ~[~str] = ~[~"128.143.", ~"137.54."]; // probably add some more ip addresses on the way
	let mut isWahoo = false;
	let mut index = 0;

	while index < WahooIPs.len()
	{
		if peer_addr.starts_with(WahooIPs[index])
		{
			isWahoo = true;
			break;
		}
		index += 1;
	}
	//println( fmt!("is wahoo? : %?\n", isWahoo) );
	return isWahoo;
}

// get the size of a file

fn get_fileSize(file_path: &Path) -> int
{
	let mut filestream = std::rt::io::file::open(file_path, Open, Read);
	let mut size:int = 0;

	// find the File size
	match filestream{
		Some(ref mut reader) =>
		{
			reader.seek(0,SeekEnd);
			size = reader.tell() as int;
			reader.seek(0, SeekSet); // rewind the file back

			println(fmt!("\nfile size: %? bytes \n", size ));
		},
		None => { fail!("\nCannot read the storage file \n");},
	}
	return size;
}

fn main() {

    let visitor_count: uint = 0; // @@@@@@@

    let mut isWahoo: bool = false;

    let req_vec: ~[sched_msg] = ~[];
    let shared_req_vec = arc::RWArc::new(req_vec);
    let add_vec = shared_req_vec.clone();
    let take_vec = shared_req_vec.clone();

    let (port, chan) = stream();
    let chan = SharedChan::new(chan);

    // dequeue file requests, and send responses.
    // FIFO
    do spawn {
        let (sm_port, sm_chan) = stream();
        let (sm_port2, sm_chan2) = stream();
        // a task for sending responses.
        do spawn {
	    let mut cache: HashMap<~str, ~[u8]> = std::hashmap::HashMap::new();
	    let mut cacheTimes: HashMap<~str, ~i64> = std::hashmap::HashMap::new();
            loop {
		sm_chan2.send(1);
                let mut tf: sched_msg = sm_port.recv(); // wait for the dequeued request to handle

		let modifiedTime = match file::stat(tf.filepath) {
			Some(s) => {
					s.modified
				   }
			None => {
					-1
				}
		};
		if cache.contains_key_equiv(&tf.filepath.to_str()) &&
				*cacheTimes.get_copy(&tf.filepath.to_str()) as u64 > modifiedTime {
			println(fmt!("begin serving file [%?]", tf.filepath));
                        // A web server should always reply a HTTP header for any legal HTTP request.
                        tf.stream.write("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n".as_bytes());
			let data = cache.get_copy(&tf.filepath.to_str());
                        tf.stream.write(data);
                        println(fmt!("finish file [%?]", tf.filepath));
		}
		else {
		     let file = io::read_whole_file(tf.filepath);
   	             match file { // killed if file size is larger than memory size.
                	    Ok(file_data) => {
                 	       println(fmt!("begin serving file [%?]", tf.filepath));
                 	       // A web server should always reply a HTTP header for any legal HTTP request.
                 	       tf.stream.write("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n".as_bytes());
                        	tf.stream.write(file_data);
                        	println(fmt!("finish file [%?]", tf.filepath));
				cache.insert(tf.filepath.to_str(), file_data);
				cacheTimes.insert(tf.filepath.to_str(), ~time::get_time().sec);
                    	    }
                    	    Err(err) => {
                        	println(err);
                    	    }
                    }
		}
            }
        }

        loop {
	    sm_port2.recv();
            port.recv(); // wait for arrving notification
            do take_vec.write |vec| {
                if ((*vec).len() > 0) {
                    // LIFO didn't make sense in service scheduling, so we modify it as FIFO by using shift_opt() rather than pop().
                    let tf_opt: Option<sched_msg> = (*vec).shift_opt();
                    let tf = tf_opt.unwrap();
                    println(fmt!("shift from queue, size: %ud", (*vec).len()));
                    sm_chan.send(tf); // send the request to send-response-task to serve.
                }
            }
        }
    }

    let ip = match FromStr::from_str(IP) { Some(ip) => ip,
					   None     => {println(fmt!("Error: Invalid IP address <%s>", IP));
						        return;}
 					 };

    let socket = net::tcp::TcpListener::bind(SocketAddr {ip: ip, port: PORT as u16});

    println(fmt!("Listening on %s:%d ...", ip.to_str(), PORT));
    let mut acceptor = socket.listen().unwrap();

    let shared_count = arc::RWArc::new( visitor_count ); // @@@@@@

    for stream in acceptor.incoming() {
	let mut stream = stream; // @@@@@@
	let mut peer_addr: ~str = ~"";

	match stream {
		Some(ref mut s) =>
		{
			match s.peer_name() {
				Some(pn) =>
				{ 	peer_addr = pn.to_str();
					println( fmt!("\nPeer address: %s", peer_addr ));
				},
				None 	 => ()
			}
		}
		None => ()
	} 			// @@@@@

	isWahoo = is_Wahoo_Client(peer_addr);
	println( fmt!("is wahoo? : %?\n", isWahoo) );

	let stream = Cell::new(stream);

	let (count_port, count_chan): (Port< extra::arc::RWArc<uint> >, Chan< extra::arc::RWArc<uint> >) = std::comm::stream(); // @@@@@@
        let count_chan = SharedChan::new(count_chan); // @@@@@@
        count_chan.send(shared_count.clone() ); // @@@@@@

        // Start a new task to handle the connection
        let child_chan = chan.clone();
	let child_add_vec = add_vec.clone();

        do spawn {

	    let shared_count_copy = count_port.recv(); // @@@@@@

	    /* Get Write Access */
	    do shared_count_copy.write |count|{
			*count = *count + 1;
			println( fmt!("count: %? \n", *count as int) );
    	    }

            let mut stream = stream.take();
            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);

            let req_group : ~[&str]= request_str.splitn_iter(' ', 3).collect();
            if req_group.len() > 2 {
                let path = req_group[1];
                println(fmt!("Request for path: \n%?", path));

                let file_path = ~os::getcwd().push(path.replace("/../", ""));

                if !os::path_exists(file_path) || os::path_is_dir(file_path)
		{
                    println(fmt!("Request received:\n%s", request_str));

		    /* Get Read Access */
		    do shared_count_copy.read |count|
		    {
   			let response: ~str = fmt!(
                        "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
			<doctype !html>
			<title>Hello, Rust!</title>

Greetings, Krusty!

Visitor count: %u

			\r\n", *count);

			stream.write(response.as_bytes());
    	    	    }

                }
                else {
                    // Requests scheduling

		    let size:int = get_fileSize(file_path); // @@@@@@@@@@@

                    let msg: sched_msg = sched_msg{stream: stream, filepath: file_path.clone()};
                    let (sm_port, sm_chan) = std::comm::stream();
                    sm_chan.send(msg);

                    do child_add_vec.write |vec| {
                        let msg = sm_port.recv();
                        (*vec).push(msg); // enqueue new request.
                        println("add to queue");
                    }
                    child_chan.send(""); //notify the new arriving request.

                    println(fmt!("get file request: %?", file_path));
                }
            }
            println!("connection terminates\n")
        }
    }
}

<|endoftext|>


<commit_before>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the MIT License, <LICENSE or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.

use bincode::{self, SizeLimit};
use bincode::serde::{deserialize_from, serialize_into};
use serde;
use std::io::{self, Read, Write};
use std::convert;
use std::sync::Arc;
use std::time::Duration;

mod client;
mod server;
mod packet;

pub use self::packet::Packet;
pub use self::client::{Client, Future};
pub use self::server::{Serve, ServeHandle};

/// Client errors that can occur during rpc calls
#[derive(Debug, Clone)]
pub enum Error {
    /// An IO-related error
    Io(Arc<io::Error>),
    /// The server hung up.
    ConnectionBroken,
}

impl convert::From<bincode::serde::SerializeError> for Error {
    fn from(err: bincode::serde::SerializeError) -> Error {
        match err {
            bincode::serde::SerializeError::IoError(err) => Error::Io(Arc::new(err)),
            err => panic!("Unexpected error during serialization: {:?}", err),
        }
    }
}

impl convert::From<bincode::serde::DeserializeError> for Error {
    fn from(err: bincode::serde::DeserializeError) -> Error {
        match err {
            bincode::serde::DeserializeError::IoError(ref err)
                if err.kind() == io::ErrorKind::ConnectionReset => Error::ConnectionBroken,
            bincode::serde::DeserializeError::EndOfStreamError => Error::ConnectionBroken,
            bincode::serde::DeserializeError::IoError(err) => Error::Io(Arc::new(err)),
            err => panic!("Unexpected error during deserialization: {:?}", err),
        }
    }
}

impl convert::From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(Arc::new(err))
    }
}

/// Configuration for client and server.
#[derive(Clone, Copy, Debug, Default, Hash, Eq, Ord, PartialEq, PartialOrd)]
pub struct Config {
    /// Request/Response timeout between packet delivery.
    pub timeout: Option<Duration>,
}

/// Return type of rpc calls: either the successful return value, or a client error.
pub type Result<T> = ::std::result::Result<T, Error>;

trait Deserialize: Read + Sized {
    fn deserialize<T: serde::Deserialize>(&mut self) -> Result<T> {
        deserialize_from(self, SizeLimit::Infinite).map_err(Error::from)
    }
}

impl<R: Read> Deserialize for R {}

trait Serialize: Write + Sized {
    fn serialize<T: serde::Serialize>(&mut self, value: &T) -> Result<()> {
        try!(serialize_into(self, value, SizeLimit::Infinite));
        try!(self.flush());
        Ok(())
    }
}

impl<W: Write> Serialize for W {}

#[cfg(test)]
mod test {
    extern crate env_logger;
    use super::{Client, Config, Serve};
    use scoped_pool::Pool;
    use std::sync::{Arc, Barrier, Mutex};
    use std::thread;
    use std::time::Duration;

    fn test_timeout() -> Option<Duration> {
        Some(Duration::from_secs(1))
    }

    struct Server {
        counter: Mutex<u64>,
    }

    impl Serve for Server {
        type Request = ();
        type Reply = u64;

        fn serve(&self, _: ()) -> u64 {
            let mut counter = self.counter.lock().unwrap();
            let reply = *counter;
            *counter += 1;
            reply
        }
    }

    impl Server {
        fn new() -> Server {
            Server { counter: Mutex::new(0) }
        }

        fn count(&self) -> u64 {
            *self.counter.lock().unwrap()
        }
    }

    #[test]
    fn handle() {
        let _ = env_logger::init();
        let server = Arc::new(Server::new());
        let serve_handle = server.spawn("localhost:0").unwrap();
        let client: Client<(), u64> = Client::new(serve_handle.local_addr()).unwrap();
        drop(client);
        serve_handle.shutdown();
    }

    #[test]
    fn simple() {
        let _ = env_logger::init();
        let server = Arc::new(Server::new());
        let serve_handle = server.clone().spawn("localhost:0").unwrap();
        let addr = serve_handle.local_addr().clone();
        // The explicit type is required so that it doesn't deserialize a u32 instead of u64
        let client: Client<(), u64> = Client::new(addr).unwrap();
        assert_eq!(0, client.rpc(()).unwrap());
        assert_eq!(1, server.count());
        assert_eq!(1, client.rpc(()).unwrap());
        assert_eq!(2, server.count());
        drop(client);
        serve_handle.shutdown();
    }

    struct BarrierServer {
        barrier: Barrier,
        inner: Server,
    }

    impl Serve for BarrierServer {
        type Request = ();
        type Reply = u64;
        fn serve(&self, request: ()) -> u64 {
            self.barrier.wait();
            self.inner.serve(request)
        }
    }

    impl BarrierServer {
        fn new(n: usize) -> BarrierServer {
            BarrierServer {
                barrier: Barrier::new(n),
                inner: Server::new(),
            }
        }

        fn count(&self) -> u64 {
            self.inner.count()
        }
    }

    #[test]
    fn force_shutdown() {
        let _ = env_logger::init();
        let server = Arc::new(Server::new());
        let serve_handle = server.spawn_with_config("localhost:0",
                                                    Config {
                                                        timeout: Some(Duration::new(0, 10))
                                                    })
                                 .unwrap();
        let addr = serve_handle.local_addr().clone();
        let client: Client<(), u64> = Client::new(addr).unwrap();
        let thread = thread::spawn(move || serve_handle.shutdown());
        info!("force_shutdown:: rpc1: {:?}", client.rpc(()));
        thread.join().unwrap();
    }

    #[test]
    fn client_failed_rpc() {
        let _ = env_logger::init();
        let server = Arc::new(Server::new());
        let serve_handle = server.spawn_with_config("localhost:0",
                                                    Config {
                                                        timeout: test_timeout(),
                                                    })
                                 .unwrap();
        let addr = serve_handle.local_addr().clone();
        let client: Arc<Client<(), u64>> = Arc::new(Client::new(addr).unwrap());
        client.rpc(()).unwrap();
        serve_handle.shutdown();
        match client.rpc(()) {
            Err(super::Error::ConnectionBroken) => {} // success
            otherwise => panic!("Expected Err(ConnectionBroken), got {:?}", otherwise),
        }
        let _ = client.rpc(()); // Test whether second failure hangs
    }

    #[test]
    fn concurrent() {
        let _ = env_logger::init();
        let concurrency = 10;
        let pool = Pool::new(concurrency);
        let server = Arc::new(BarrierServer::new(concurrency));
        let serve_handle = server.clone().spawn("localhost:0").unwrap();
        let addr = serve_handle.local_addr().clone();
        let client: Client<(), u64> = Client::new(addr).unwrap();
        pool.scoped(|scope| {
            for _ in 0..concurrency {
                let client = client.try_clone().unwrap();
                scope.execute(move || {
                    client.rpc(()).unwrap();
                });
            }
        });
        assert_eq!(concurrency as u64, server.count());
        drop(client);
        serve_handle.shutdown();
    }

    #[test]
    fn async() {
        let _ = env_logger::init();
        let server = Arc::new(Server::new());
        let serve_handle = server.spawn("localhost:0").unwrap();
        let addr = serve_handle.local_addr().clone();
        let client: Client<(), u64> = Client::new(addr).unwrap();

        // Drop future immediately; does the reader channel panic when sending?
        client.rpc_async(());
        // If the reader panicked, this won't succeed
        client.rpc_async(());

        drop(client);
        serve_handle.shutdown();
    }
}
<commit_msg>Don't derive Hash for Config because Duration is only Hashable on nightly<commit_after>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the MIT License, <LICENSE or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.

use bincode::{self, SizeLimit};
use bincode::serde::{deserialize_from, serialize_into};
use serde;
use std::io::{self, Read, Write};
use std::convert;
use std::sync::Arc;
use std::time::Duration;

mod client;
mod server;
mod packet;

pub use self::packet::Packet;
pub use self::client::{Client, Future};
pub use self::server::{Serve, ServeHandle};

/// Client errors that can occur during rpc calls
#[derive(Debug, Clone)]
pub enum Error {
    /// An IO-related error
    Io(Arc<io::Error>),
    /// The server hung up.
    ConnectionBroken,
}

impl convert::From<bincode::serde::SerializeError> for Error {
    fn from(err: bincode::serde::SerializeError) -> Error {
        match err {
            bincode::serde::SerializeError::IoError(err) => Error::Io(Arc::new(err)),
            err => panic!("Unexpected error during serialization: {:?}", err),
        }
    }
}

impl convert::From<bincode::serde::DeserializeError> for Error {
    fn from(err: bincode::serde::DeserializeError) -> Error {
        match err {
            bincode::serde::DeserializeError::IoError(ref err)
                if err.kind() == io::ErrorKind::ConnectionReset => Error::ConnectionBroken,
            bincode::serde::DeserializeError::EndOfStreamError => Error::ConnectionBroken,
            bincode::serde::DeserializeError::IoError(err) => Error::Io(Arc::new(err)),
            err => panic!("Unexpected error during deserialization: {:?}", err),
        }
    }
}

impl convert::From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(Arc::new(err))
    }
}

/// Configuration for client and server.
#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
pub struct Config {
    /// Request/Response timeout between packet delivery.
    pub timeout: Option<Duration>,
}

/// Return type of rpc calls: either the successful return value, or a client error.
pub type Result<T> = ::std::result::Result<T, Error>;

trait Deserialize: Read + Sized {
    fn deserialize<T: serde::Deserialize>(&mut self) -> Result<T> {
        deserialize_from(self, SizeLimit::Infinite).map_err(Error::from)
    }
}

impl<R: Read> Deserialize for R {}

trait Serialize: Write + Sized {
    fn serialize<T: serde::Serialize>(&mut self, value: &T) -> Result<()> {
        try!(serialize_into(self, value, SizeLimit::Infinite));
        try!(self.flush());
        Ok(())
    }
}

impl<W: Write> Serialize for W {}

#[cfg(test)]
mod test {
    extern crate env_logger;
    use super::{Client, Config, Serve};
    use scoped_pool::Pool;
    use std::sync::{Arc, Barrier, Mutex};
    use std::thread;
    use std::time::Duration;

    fn test_timeout() -> Option<Duration> {
        Some(Duration::from_secs(1))
    }

    struct Server {
        counter: Mutex<u64>,
    }

    impl Serve for Server {
        type Request = ();
        type Reply = u64;

        fn serve(&self, _: ()) -> u64 {
            let mut counter = self.counter.lock().unwrap();
            let reply = *counter;
            *counter += 1;
            reply
        }
    }

    impl Server {
        fn new() -> Server {
            Server { counter: Mutex::new(0) }
        }

        fn count(&self) -> u64 {
            *self.counter.lock().unwrap()
        }
    }

    #[test]
    fn handle() {
        let _ = env_logger::init();
        let server = Arc::new(Server::new());
        let serve_handle = server.spawn("localhost:0").unwrap();
        let client: Client<(), u64> = Client::new(serve_handle.local_addr()).unwrap();
        drop(client);
        serve_handle.shutdown();
    }

    #[test]
    fn simple() {
        let _ = env_logger::init();
        let server = Arc::new(Server::new());
        let serve_handle = server.clone().spawn("localhost:0").unwrap();
        let addr = serve_handle.local_addr().clone();
        // The explicit type is required so that it doesn't deserialize a u32 instead of u64
        let client: Client<(), u64> = Client::new(addr).unwrap();
        assert_eq!(0, client.rpc(()).unwrap());
        assert_eq!(1, server.count());
        assert_eq!(1, client.rpc(()).unwrap());
        assert_eq!(2, server.count());
        drop(client);
        serve_handle.shutdown();
    }

    struct BarrierServer {
        barrier: Barrier,
        inner: Server,
    }

    impl Serve for BarrierServer {
        type Request = ();
        type Reply = u64;
        fn serve(&self, request: ()) -> u64 {
            self.barrier.wait();
            self.inner.serve(request)
        }
    }

    impl BarrierServer {
        fn new(n: usize) -> BarrierServer {
            BarrierServer {
                barrier: Barrier::new(n),
                inner: Server::new(),
            }
        }

        fn count(&self) -> u64 {
            self.inner.count()
        }
    }

    #[test]
    fn force_shutdown() {
        let _ = env_logger::init();
        let server = Arc::new(Server::new());
        let serve_handle = server.spawn_with_config("localhost:0",
                                                    Config {
                                                        timeout: Some(Duration::new(0, 10))
                                                    })
                                 .unwrap();
        let addr = serve_handle.local_addr().clone();
        let client: Client<(), u64> = Client::new(addr).unwrap();
        let thread = thread::spawn(move || serve_handle.shutdown());
        info!("force_shutdown:: rpc1: {:?}", client.rpc(()));
        thread.join().unwrap();
    }

    #[test]
    fn client_failed_rpc() {
        let _ = env_logger::init();
        let server = Arc::new(Server::new());
        let serve_handle = server.spawn_with_config("localhost:0",
                                                    Config {
                                                        timeout: test_timeout(),
                                                    })
                                 .unwrap();
        let addr = serve_handle.local_addr().clone();
        let client: Arc<Client<(), u64>> = Arc::new(Client::new(addr).unwrap());
        client.rpc(()).unwrap();
        serve_handle.shutdown();
        match client.rpc(()) {
            Err(super::Error::ConnectionBroken) => {} // success
            otherwise => panic!("Expected Err(ConnectionBroken), got {:?}", otherwise),
        }
        let _ = client.rpc(()); // Test whether second failure hangs
    }

    #[test]
    fn concurrent() {
        let _ = env_logger::init();
        let concurrency = 10;
        let pool = Pool::new(concurrency);
        let server = Arc::new(BarrierServer::new(concurrency));
        let serve_handle = server.clone().spawn("localhost:0").unwrap();
        let addr = serve_handle.local_addr().clone();
        let client: Client<(), u64> = Client::new(addr).unwrap();
        pool.scoped(|scope| {
            for _ in 0..concurrency {
                let client = client.try_clone().unwrap();
                scope.execute(move || {
                    client.rpc(()).unwrap();
                });
            }
        });
        assert_eq!(concurrency as u64, server.count());
        drop(client);
        serve_handle.shutdown();
    }

    #[test]
    fn async() {
        let _ = env_logger::init();
        let server = Arc::new(Server::new());
        let serve_handle = server.spawn("localhost:0").unwrap();
        let addr = serve_handle.local_addr().clone();
        let client: Client<(), u64> = Client::new(addr).unwrap();

        // Drop future immediately; does the reader channel panic when sending?
        client.rpc_async(());
        // If the reader panicked, this won't succeed
        client.rpc_async(());

        drop(client);
        serve_handle.shutdown();
    }
}
<|endoftext|>