<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
Syntax extension to generate FourCCs.

Once loaded, fourcc!() is called with a single 4-character string,
and an optional ident that is either `big`, `little`, or `target`.
The ident represents endianness, and specifies in which direction
the characters should be read. If the ident is omitted, it is assumed
to be `big`, i.e. left-to-right order. It returns a u32.

# Examples

To load the extension and use it:

```rust,ignore
#[phase(plugin)]
extern crate fourcc;

fn main() {
    let val = fourcc!("\xC0\xFF\xEE!");
    assert_eq!(val, 0xC0FFEE21u32);
    let little_val = fourcc!("foo ", little);
    assert_eq!(little_val, 0x21EEFFC0u32);
}
```

# References

* [Wikipedia: FourCC](http://en.wikipedia.org/wiki/FourCC)

*/

#![crate_name = "fourcc"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![license = "MIT/ASL2"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico")]

#![feature(plugin_registrar, managed_boxes)]

extern crate syntax;
extern crate rustc;

use syntax::ast;
use syntax::attr::contains;
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
use syntax::ext::base::{ExtCtxt, MacExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
use syntax::parse::token::InternedString;
use rustc::plugin::Registry;

use std::gc::Gc;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("fourcc", expand_syntax_ext);
}

pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                         -> Box<base::MacResult + 'static> {
    let (expr, endian) = parse_tts(cx, tts);

    let little = match endian {
        None => false,
        Some(Ident{ident, span}) => match token::get_ident(ident).get() {
            "little" => true,
            "big" => false,
            "target" => target_endian_little(cx, sp),
            _ => {
                cx.span_err(span, "invalid endian directive in fourcc!");
                target_endian_little(cx, sp)
            }
        }
    };

    let s = match expr.node {
        // expression is a literal
        ast::ExprLit(ref lit) => match lit.node {
            // string literal
            ast::LitStr(ref s, _) => {
                if s.get().char_len() != 4 {
                    cx.span_err(expr.span, "string literal with len != 4 in fourcc!");
                }
                s
            }
            _ => {
                cx.span_err(expr.span, "unsupported literal in fourcc!");
                return base::DummyResult::expr(sp)
            }
        },
        _ => {
            cx.span_err(expr.span, "non-literal in fourcc!");
            return base::DummyResult::expr(sp)
        }
    };

    let mut val = 0u32;
    for codepoint in s.get().chars().take(4) {
        let byte = if codepoint as u32 > 0xFF {
            cx.span_err(expr.span, "fourcc! literal character out of range 0-255");
            0u8
        } else {
            codepoint as u8
        };

        val = if little {
            (val >> 8) | ((byte as u32) << 24)
        } else {
            (val << 8) | (byte as u32)
        };
    }
    let e = cx.expr_lit(sp, ast::LitInt(val as u64, ast::UnsignedIntLit(ast::TyU32)));
    MacExpr::new(e)
}

struct Ident {
    ident: ast::Ident,
    span: Span
}

fn parse_tts(cx: &ExtCtxt,
             tts: &[ast::TokenTree]) -> (Gc<ast::Expr>, Option<Ident>) {
    let p = &mut cx.new_parser_from_tts(tts);
    let ex = p.parse_expr();
    let id = if p.token == token::EOF {
        None
    } else {
        p.expect(&token::COMMA);
        let lo = p.span.lo;
        let ident = p.parse_ident();
        let hi = p.last_span.hi;
        Some(Ident{ident: ident, span: mk_sp(lo, hi)})
    };
    if p.token != token::EOF {
        p.unexpected();
    }
    (ex, id)
}

fn target_endian_little(cx: &ExtCtxt, sp: Span) -> bool {
    let meta = cx.meta_name_value(sp, InternedString::new("target_endian"),
        ast::LitStr(InternedString::new("little"), ast::CookedStr));
    contains(cx.cfg().as_slice(), meta)
}

// FIXME (10872): This is required to prevent an LLVM assert on Windows
#[test]
fn dummy_test() { }
<commit_msg>Update to rust master<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
Syntax extension to generate FourCCs.

Once loaded, fourcc!() is called with a single 4-character string,
and an optional ident that is either `big`, `little`, or `target`.
The ident represents endianness, and specifies in which direction
the characters should be read. If the ident is omitted, it is assumed
to be `big`, i.e. left-to-right order. It returns a u32.

# Examples

To load the extension and use it:

```rust,ignore
#[phase(plugin)]
extern crate fourcc;

fn main() {
    let val = fourcc!("\xC0\xFF\xEE!");
    assert_eq!(val, 0xC0FFEE21u32);
    let little_val = fourcc!("foo ", little);
    assert_eq!(little_val, 0x21EEFFC0u32);
}
```

# References

* [Wikipedia: FourCC](http://en.wikipedia.org/wiki/FourCC)

*/

#![crate_name = "fourcc"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![license = "MIT/ASL2"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico")]

#![feature(plugin_registrar, managed_boxes)]

extern crate syntax;
extern crate rustc;

use syntax::ast;
use syntax::attr::contains;
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
use syntax::ext::base::{ExtCtxt, MacExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
use syntax::parse::token::InternedString;
use syntax::ptr::P;
use rustc::plugin::Registry;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("fourcc", expand_syntax_ext);
}

pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                         -> Box<base::MacResult + 'static> {
    let (expr, endian) = parse_tts(cx, tts);

    let little = match endian {
        None => false,
        Some(Ident{ident, span}) => match token::get_ident(ident).get() {
            "little" => true,
            "big" => false,
            "target" => target_endian_little(cx, sp),
            _ => {
                cx.span_err(span, "invalid endian directive in fourcc!");
                target_endian_little(cx, sp)
            }
        }
    };

    let s = match expr.node {
        // expression is a literal
        ast::ExprLit(ref lit) => match lit.node {
            // string literal
            ast::LitStr(ref s, _) => {
                if s.get().char_len() != 4 {
                    cx.span_err(expr.span, "string literal with len != 4 in fourcc!");
                }
                s
            }
            _ => {
                cx.span_err(expr.span, "unsupported literal in fourcc!");
                return base::DummyResult::expr(sp)
            }
        },
        _ => {
            cx.span_err(expr.span, "non-literal in fourcc!");
            return base::DummyResult::expr(sp)
        }
    };

    let mut val = 0u32;
    for codepoint in s.get().chars().take(4) {
        let byte = if codepoint as u32 > 0xFF {
            cx.span_err(expr.span, "fourcc! literal character out of range 0-255");
            0u8
        } else {
            codepoint as u8
        };

        val = if little {
            (val >> 8) | ((byte as u32) << 24)
        } else {
            (val << 8) | (byte as u32)
        };
    }
    let e = cx.expr_lit(sp, ast::LitInt(val as u64, ast::UnsignedIntLit(ast::TyU32)));
    MacExpr::new(e)
}

struct Ident {
    ident: ast::Ident,
    span: Span
}

fn parse_tts(cx: &ExtCtxt,
             tts: &[ast::TokenTree]) -> (P<ast::Expr>, Option<Ident>) {
    let p = &mut cx.new_parser_from_tts(tts);
    let ex = p.parse_expr();
    let id = if p.token == token::EOF {
        None
    } else {
        p.expect(&token::COMMA);
        let lo = p.span.lo;
        let ident = p.parse_ident();
        let hi = p.last_span.hi;
        Some(Ident{ident: ident, span: mk_sp(lo, hi)})
    };
    if p.token != token::EOF {
        p.unexpected();
    }
    (ex, id)
}

fn target_endian_little(cx: &ExtCtxt, sp: Span) -> bool {
    let meta = cx.meta_name_value(sp, InternedString::new("target_endian"),
        ast::LitStr(InternedString::new("little"), ast::CookedStr));
    contains(cx.cfg().as_slice(), &*meta)
}

// FIXME (10872): This is required to prevent an LLVM assert on Windows
#[test]
fn dummy_test() { }
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::collections::HashSet;

/// A graph is represeted by as a weighted
/// [Adjenceny matrix](http://en.wikipedia.org/wiki/Adjacency_matrix)
pub struct Graph {
  /// The underlaying graph represented here with weights as an i32 (should
  /// probably be generic) the graph is represented as an
  /// [Adjenceny matrix](http://en.wikipedia.org/wiki/Adjacency_matrix) of
  /// Optionals, where None indicates that there doesn't exist a vertex and
  /// Some<i32> indicates that There is a vertex of weight i32.
  graph: Vec<Vec<Option<i32>>>
}
impl Graph {
  /// `new` allows for initializing the graph struct with a given adjecency matrix
  ///
  /// ## Arguments
  /// * `input` - an adjecency matrix in made out of a two-dimensional `Vec` of
  ///    weights. Weights are represented as `i32`:s and can thus be positive or
  ///    negative numbers.
  ///
  /// ## Example
  /// ```ignore
  ///  let rawgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None],
  ///                      vec![   None,  Some(0),     None,     None,     None,     None],
  ///                      vec![   None,     None,  Some(0),     None,     None,     None],
  ///                      vec![   None,     None,     None,  Some(0), Some(50),     None],
  ///                      vec![   None,     None, Some(20),     None,  Some(0), Some(50)],
  ///                      vec![   None,     None,     None,     None,     None,  Some(0)]];
  /// let g = Graph::new(rawgraph);
  /// ```
  pub fn new(input: Vec<Vec<Option<i32>>>) -> Graph { Graph { graph: input } }

  /// `breadth_first_search` implements breadth first search from `start` to the
  /// `target` and returns the path found as a `VecDeque<usize>` of nodes. This
  /// is an optional type as there might not be a path.
  ///
  /// **NOTE** as this is breadth first search this search ignores any assigned
  /// weight to nodes.
  ///
  /// ## Arguments
  /// * `start`  - an `usize` designating the start node, or row in the adjecency matrix
  /// * `target` - an `usize` designating the target node, or row in the adjecency matrix
  ///
  /// ## Returns
  /// Either the found path between start and target as a `VecDeque` of `usize`:s
  /// or `None` if there is no path.
  pub fn breadth_first_search(&self, start: usize, target: usize) -> Option<VecDeque<usize>> {
    return self.inner_search(start, target, true)
  }

  /// `depth_first_search` implements depth first search from `start` to the
  /// `target` and returns the path found as a `VecDeque<usize>` of nodes. This
  /// is an optional type as there might not be a path.
  ///
  /// **NOTE** as this is depth first search this search ignores any assigned
  /// weight to nodes.
  ///
  /// ## Arguments
  /// * `start`  - an `usize` designating the start node, or row in the adjecency matrix
  /// * `target` - an `usize` designating the target node, or row in the adjecency matrix
  ///
  /// ## Returns
  /// Either the found path between start and target as a `VecDeque` of `usize`:s
  /// or `None` if there is no path.
  pub fn depth_first_search(&self, start: usize, target: usize) -> Option<VecDeque<usize>> {
    return self.inner_search(start, target, false)
  }

  fn inner_search(&self, start: usize, target: usize, bfs: bool) -> Option<VecDeque<usize>>  {
    let mut q: VecDeque<usize> = VecDeque::new();
    let mut discovered: HashSet<usize> = HashSet::new();
    let mut prev: Vec<usize> = Vec::with_capacity(self.graph.len());
    let mut pathfound = false;
    for _ in (0..self.graph.len()) { prev.push(0); }

    q.push_back(start);
    discovered.insert(start);

    while !q.is_empty() {
      let mut v: Option<usize>;
      if bfs {
        v = q.pop_front()
      } else {
        v = q.pop_back();
      }
      match v {
        None => {}, // q is empty
        Some(v) => { // we are working on a new layer
          if !discovered.contains(&v) { discovered.insert(v); }
          if v == target { pathfound = true; }
          for i in (0..self.graph[v].len()) {
            match self.graph[v][i] {
              None => {}, // no vertex between v and i
              Some(_) => {
                if !discovered.contains(&i) {
                  q.push_back(i);
                  prev[i]=v; //track prev (v) on i
                }
              }
            }
          }
        }
      }
    }
    if pathfound {
      let mut path: VecDeque<usize> = VecDeque::new();
      let mut curr = target;
      // backtrack over the prev array to construct the path
      while curr != start {
        path.push_front(curr);
        curr = prev[curr];
      }
      path.push_front(start);
      return Some(path)
    }
    return None
  }

  pub fn cost_of_path(&self, path: VecDeque<usize>) -> i32 {
    let mut cost = 0;
    for i in (0..path.len()-1) {
      match self.graph[path[i]][path[i+1]] {
        None => {},
        Some(c) => { cost = cost + c; }
      }
    }
    return cost
  }
}

#[test]
fn breadth_first_search_test() {
  let testgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None, None],
                       vec![   None,  Some(0),     None,     None,     None,     None, None],
                       vec![   None,     None,  Some(0),     None,     None,     None,  Some(50)],
                       vec![   None,     None,     None,  Some(0), Some(50),     None, None],
                       vec![   None,     None, Some(20),     None,  Some(0), Some(50),  Some(40)],
                       vec![   None,     None,     None,     None,     None,  Some(0), None],
                       vec![   None,     None,     None,     None,     None,     None, Some(0)]];
  let start: usize = 0;
  let target: usize = 6;
  let g = Graph::new(testgraph);
  let res = g.breadth_first_search(start, target);
  match res {
    None => {
      println!("Breadth first search returned None");
      assert!(false);
    }
    Some(result) => {
      println!("Breadth first search returned something: {:?}", result);
      assert_eq!(result[result.len()-1], target);
      assert_eq!(result[0], start);
    }
  }
}

#[test]
fn breadth_first_search_test_no_valid_path() {
  let testgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None, None],
                       vec![   None,  Some(0),     None,     None,     None,     None, None],
                       vec![   None,     None,  Some(0),     None,     None,     None,  Some(50)],
                       vec![   None,     None,     None,  Some(0), Some(50),     None, None],
                       vec![   None,     None, Some(20),     None,  Some(0),     None,  Some(40)],
                       vec![   None,     None,     None,     None,     None,  Some(0), None],
                       vec![   None,     None,     None,     None,     None,     None, Some(0)]];
  let start: usize = 0;
  let target: usize = 5; // There is no valid path between 0 and 5
  let g = Graph::new(testgraph);
  let res = g.breadth_first_search(start, target);

  // The expected return value is None
  match res {
    None => {
      println!("Breadth first search returned None");
      assert!(true);
    }
    Some(result) => {
      println!("Breadth first search returned something: {:?}", result);
      assert_eq!(result[result.len()-1], target);
      assert_eq!(result[0], start);
      assert!(false);
    }
  }
}

#[test]
fn depth_first_search_test() {
  let testgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None, None],
                       vec![   None,  Some(0),     None,     None,     None,     None, None],
                       vec![   None,     None,  Some(0),     None,     None,     None,  Some(50)],
                       vec![   None,     None,     None,  Some(0), Some(50),     None, None],
                       vec![   None,     None, Some(20),     None,  Some(0), Some(50),  Some(40)],
                       vec![   None,     None,     None,     None,     None,  Some(0), None],
                       vec![   None,     None,     None,     None,     None,     None, Some(0)]];
  let start: usize = 0;
  let target: usize = 6;
  let g = Graph::new(testgraph);
  let res = g.depth_first_search(start, target);
  match res {
    None => {
      println!("Depth first search returned None");
      assert!(false);
    }
    Some(result) => {
      println!("Depth first search returned something: {:?}", result);
      assert_eq!(result[result.len()-1], target);
      assert_eq!(result[0], start);
    }
  }
}

#[test]
fn depth_first_search_test_no_valid_path() {
  let testgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None, None],
                       vec![   None,  Some(0),     None,     None,     None,     None, None],
                       vec![   None,     None,  Some(0),     None,     None,     None,  Some(50)],
                       vec![   None,     None,     None,  Some(0), Some(50),     None, None],
                       vec![   None,     None, Some(20),     None,  Some(0),     None,  Some(40)],
                       vec![   None,     None,     None,     None,     None,  Some(0), None],
                       vec![   None,     None,     None,     None,     None,     None, Some(0)]];
  let start: usize = 0;
  let target: usize = 5; // There is no valid path between 0 and 5
  let g = Graph::new(testgraph);
  let res = g.depth_first_search(start, target);

  // The expected return value is None
  match res {
    None => {
      println!("Depth first search returned None");
      assert!(true);
    }
    Some(result) => {
      println!("Depth first search returned something: {:?}", result);
      assert_eq!(result[result.len()-1], target);
      assert_eq!(result[0], start);
      assert!(false);
    }
  }
}
<commit_msg>Added some documentation on the cost_of_path function<commit_after>use std::collections::VecDeque;
use std::collections::HashSet;

/// A graph is represeted by as a weighted
/// [Adjenceny matrix](http://en.wikipedia.org/wiki/Adjacency_matrix)
pub struct Graph {
  /// The underlaying graph represented here with weights as an i32 (should
  /// probably be generic) the graph is represented as an
  /// [Adjenceny matrix](http://en.wikipedia.org/wiki/Adjacency_matrix) of
  /// Optionals, where None indicates that there doesn't exist a vertex and
  /// Some<i32> indicates that There is a vertex of weight i32.
  graph: Vec<Vec<Option<i32>>>
}
impl Graph {
  /// `new` allows for initializing the graph struct with a given adjecency matrix
  ///
  /// ## Arguments
  /// * `input` - an adjecency matrix in made out of a two-dimensional `Vec` of
  ///    weights. Weights are represented as `i32`:s and can thus be positive or
  ///    negative numbers.
  ///
  /// ## Example
  /// ```ignore
  ///  let rawgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None],
  ///                      vec![   None,  Some(0),     None,     None,     None,     None],
  ///                      vec![   None,     None,  Some(0),     None,     None,     None],
  ///                      vec![   None,     None,     None,  Some(0), Some(50),     None],
  ///                      vec![   None,     None, Some(20),     None,  Some(0), Some(50)],
  ///                      vec![   None,     None,     None,     None,     None,  Some(0)]];
  /// let g = Graph::new(rawgraph);
  /// ```
  pub fn new(input: Vec<Vec<Option<i32>>>) -> Graph { Graph { graph: input } }

  /// `breadth_first_search` implements breadth first search from `start` to the
  /// `target` and returns the path found as a `VecDeque<usize>` of nodes. This
  /// is an optional type as there might not be a path.
  ///
  /// **NOTE** as this is breadth first search this search ignores any assigned
  /// weight to nodes.
  ///
  /// ## Arguments
  /// * `start`  - an `usize` designating the start node, or row in the adjecency matrix
  /// * `target` - an `usize` designating the target node, or row in the adjecency matrix
  ///
  /// ## Returns
  /// Either the found path between start and target as a `VecDeque` of `usize`:s
  /// or `None` if there is no path.
  pub fn breadth_first_search(&self, start: usize, target: usize) -> Option<VecDeque<usize>> {
    return self.inner_search(start, target, true)
  }

  /// `depth_first_search` implements depth first search from `start` to the
  /// `target` and returns the path found as a `VecDeque<usize>` of nodes. This
  /// is an optional type as there might not be a path.
  ///
  /// **NOTE** as this is depth first search this search ignores any assigned
  /// weight to nodes.
  ///
  /// ## Arguments
  /// * `start`  - an `usize` designating the start node, or row in the adjecency matrix
  /// * `target` - an `usize` designating the target node, or row in the adjecency matrix
  ///
  /// ## Returns
  /// Either the found path between start and target as a `VecDeque` of `usize`:s
  /// or `None` if there is no path.
  pub fn depth_first_search(&self, start: usize, target: usize) -> Option<VecDeque<usize>> {
    return self.inner_search(start, target, false)
  }

  fn inner_search(&self, start: usize, target: usize, bfs: bool) -> Option<VecDeque<usize>>  {
    let mut q: VecDeque<usize> = VecDeque::new();
    let mut discovered: HashSet<usize> = HashSet::new();
    let mut prev: Vec<usize> = Vec::with_capacity(self.graph.len());
    let mut pathfound = false;
    for _ in (0..self.graph.len()) { prev.push(0); }

    q.push_back(start);
    discovered.insert(start);

    while !q.is_empty() {
      let mut v: Option<usize>;
      if bfs {
        v = q.pop_front()
      } else {
        v = q.pop_back();
      }
      match v {
        None => {}, // q is empty
        Some(v) => { // we are working on a new layer
          if !discovered.contains(&v) { discovered.insert(v); }
          if v == target { pathfound = true; }
          for i in (0..self.graph[v].len()) {
            match self.graph[v][i] {
              None => {}, // no vertex between v and i
              Some(_) => {
                if !discovered.contains(&i) {
                  q.push_back(i);
                  prev[i]=v; //track prev (v) on i
                }
              }
            }
          }
        }
      }
    }
    if pathfound {
      let mut path: VecDeque<usize> = VecDeque::new();
      let mut curr = target;
      // backtrack over the prev array to construct the path
      while curr != start {
        path.push_front(curr);
        curr = prev[curr];
      }
      path.push_front(start);
      return Some(path)
    }
    return None
  }

  /// `cost_of_path` takes a path returned from any of the search functions and
  /// calculates the cost of the path.
  ///
  /// ## Arguments
  /// * `path` - a `VecDeque<usize>` representing a path through the graph
  ///
  /// ## Returns
  /// The cost of traversing said path represented as an `i32`
  pub fn cost_of_path(&self, path: VecDeque<usize>) -> i32 {
    let mut cost = 0;
    for i in (0..path.len()-1) {
      match self.graph[path[i]][path[i+1]] {
        None => {},
        Some(c) => { cost = cost + c; }
      }
    }
    return cost
  }
}

#[test]
fn breadth_first_search_test() {
  let testgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None, None],
                       vec![   None,  Some(0),     None,     None,     None,     None, None],
                       vec![   None,     None,  Some(0),     None,     None,     None,  Some(50)],
                       vec![   None,     None,     None,  Some(0), Some(50),     None, None],
                       vec![   None,     None, Some(20),     None,  Some(0), Some(50),  Some(40)],
                       vec![   None,     None,     None,     None,     None,  Some(0), None],
                       vec![   None,     None,     None,     None,     None,     None, Some(0)]];
  let start: usize = 0;
  let target: usize = 6;
  let g = Graph::new(testgraph);
  let res = g.breadth_first_search(start, target);
  match res {
    None => {
      println!("Breadth first search returned None");
      assert!(false);
    }
    Some(result) => {
      println!("Breadth first search returned something: {:?}", result);
      assert_eq!(result[result.len()-1], target);
      assert_eq!(result[0], start);
    }
  }
}

#[test]
fn breadth_first_search_test_no_valid_path() {
  let testgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None, None],
                       vec![   None,  Some(0),     None,     None,     None,     None, None],
                       vec![   None,     None,  Some(0),     None,     None,     None,  Some(50)],
                       vec![   None,     None,     None,  Some(0), Some(50),     None, None],
                       vec![   None,     None, Some(20),     None,  Some(0),     None,  Some(40)],
                       vec![   None,     None,     None,     None,     None,  Some(0), None],
                       vec![   None,     None,     None,     None,     None,     None, Some(0)]];
  let start: usize = 0;
  let target: usize = 5; // There is no valid path between 0 and 5
  let g = Graph::new(testgraph);
  let res = g.breadth_first_search(start, target);

  // The expected return value is None
  match res {
    None => {
      println!("Breadth first search returned None");
      assert!(true);
    }
    Some(result) => {
      println!("Breadth first search returned something: {:?}", result);
      assert_eq!(result[result.len()-1], target);
      assert_eq!(result[0], start);
      assert!(false);
    }
  }
}

#[test]
fn depth_first_search_test() {
  let testgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None, None],
                       vec![   None,  Some(0),     None,     None,     None,     None, None],
                       vec![   None,     None,  Some(0),     None,     None,     None,  Some(50)],
                       vec![   None,     None,     None,  Some(0), Some(50),     None, None],
                       vec![   None,     None, Some(20),     None,  Some(0), Some(50),  Some(40)],
                       vec![   None,     None,     None,     None,     None,  Some(0), None],
                       vec![   None,     None,     None,     None,     None,     None, Some(0)]];
  let start: usize = 0;
  let target: usize = 6;
  let g = Graph::new(testgraph);
  let res = g.depth_first_search(start, target);
  match res {
    None => {
      println!("Depth first search returned None");
      assert!(false);
    }
    Some(result) => {
      println!("Depth first search returned something: {:?}", result);
      assert_eq!(result[result.len()-1], target);
      assert_eq!(result[0], start);
    }
  }
}

#[test]
fn depth_first_search_test_no_valid_path() {
  let testgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None, None],
                       vec![   None,  Some(0),     None,     None,     None,     None, None],
                       vec![   None,     None,  Some(0),     None,     None,     None,  Some(50)],
                       vec![   None,     None,     None,  Some(0), Some(50),     None, None],
                       vec![   None,     None, Some(20),     None,  Some(0),     None,  Some(40)],
                       vec![   None,     None,     None,     None,     None,  Some(0), None],
                       vec![   None,     None,     None,     None,     None,     None, Some(0)]];
  let start: usize = 0;
  let target: usize = 5; // There is no valid path between 0 and 5
  let g = Graph::new(testgraph);
  let res = g.depth_first_search(start, target);

  // The expected return value is None
  match res {
    None => {
      println!("Depth first search returned None");
      assert!(true);
    }
    Some(result) => {
      println!("Depth first search returned something: {:?}", result);
      assert_eq!(result[result.len()-1], target);
      assert_eq!(result[0], start);
      assert!(false);
    }
  }
}
<|endoftext|>


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

/*!
# Simple usage

## Creating the server

The easiest way to create a server is to call `Server::http()`.

The `http()` function returns an `IoResult<Server>` which will return an error
in the case where the server creation fails (for example if the listening port is already
occupied).

```no_run
let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
```

A newly-created `Server` will immediatly start listening for incoming connections and HTTP
requests.

## Receiving requests

Calling `server.recv()` will block until the next request is available.
This function returns an `IoResult<Request>`, so you need to handle the possible errors.

```no_run
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();

loop {
    // blocks until the next request is received
    let request = match server.recv() {
        Ok(rq) => rq,
        Err(e) => { println!("error: {}", e); break }
    };

    // do something with the request
    // ...
}
```

In a real-case scenario, you will probably want to spawn multiple worker tasks and call
`server.recv()` on all of them. Like this:

```no_run
# use std::sync::Arc;
# use std::thread;
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
let server = Arc::new(server);
let mut guards = Vec::with_capacity(4);

for _ in (0 .. 4) {
    let server = server.clone();

    let guard = thread::spawn(move || {
        loop {
            let rq = server.recv().unwrap();

            // ...
        }
    });

    guards.push(guard);
}
```

If you don't want to block, you can call `server.try_recv()` instead.

## Handling requests

The `Request` object returned by `server.recv()` contains informations about the client's request.
The most useful methods are probably `request.method()` and `request.url()` which return
the requested method (`GET`, `POST`, etc.) and url.

To handle a request, you need to create a `Response` object. See the docs of this object for
more infos. Here is an example of creating a `Response` from a file:

```no_run
# use std::fs::File;
# use std::path::Path;
let response = tiny_http::Response::from_file(File::open(&Path::new("image.png")).unwrap());
```

All that remains to do is call `request.respond()`:

```no_run
# use std::fs::File;
# use std::path::Path;
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
# let request = server.recv().unwrap();
# let response = tiny_http::Response::from_file(File::open(&Path::new("image.png")).unwrap());
request.respond(response)
```
*/
#![crate_name = "tiny_http"]
#![crate_type = "lib"]
#![forbid(unsafe_code)]

extern crate ascii;
extern crate chunked_transfer;
extern crate encoding;
extern crate url;
extern crate chrono;

#[cfg(feature = "ssl")]
extern crate openssl;

use std::io::Error as IoError;
use std::io::Result as IoResult;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::thread;
use std::net;
use std::net::ToSocketAddrs;

use client::ClientConnection;
use util::MessagesQueue;

pub use common::{Header, HeaderField, HTTPVersion, Method, StatusCode};
pub use request::Request;
pub use response::{ResponseBox, Response};

mod client;
mod common;
mod request;
mod response;

#[allow(dead_code)]     // TODO: remove when everything is implemented
mod util;

/// The main class of this library.
///
/// Destroying this object will immediatly close the listening socket annd the reading
///  part of all the client's connections. Requests that have already been returned by
///  the `recv()` function will not close and the responses will be transferred to the client.
pub struct Server {
    // should be false as long as the server exists
    // when set to true, all the subtasks will close within a few hundreds ms
    close: Arc<AtomicBool>,

    // queue for messages received by child threads
    messages: Arc<MessagesQueue<Message>>,

    // result of TcpListener::local_addr()
    listening_addr: net::SocketAddr,
}

enum Message {
    Error(IoError),
    NewRequest(Request),
}

impl From<IoError> for Message {
    fn from(e: IoError) -> Message {
        Message::Error(e)
    }
}

impl From<Request> for Message {
    fn from(rq: Request) -> Message {
        Message::NewRequest(rq)
    }
}

// this trait is to make sure that Server implements Share and Send
#[doc(hidden)]
trait MustBeShareDummy : Sync + Send {}
#[doc(hidden)]
impl MustBeShareDummy for Server {}

pub struct IncomingRequests<'a> {
    server: &'a Server
}

/// Represents the parameters required to create a server.
#[derive(Debug, Clone)]
pub struct ServerConfig<A> where A: ToSocketAddrs {
    /// The addresses to listen to.
    pub addr: A,
}

impl Server {
    /// Shortcut for a simple server on a specific address.
    #[inline]
    pub fn http<A>(addr: A) -> IoResult<Server>
        where A: ToSocketAddrs
    {
        Server::new(ServerConfig {
            addr: addr,
        })
    }

    /// Builds a new server that listens on the specified address.
    pub fn new<A>(config: ServerConfig<A>) -> IoResult<Server>
        where A: ToSocketAddrs
    {
        // building the "close" variable
        let close_trigger = Arc::new(AtomicBool::new(false));

        // building the TcpListener
        let (server, local_addr) = {
            let listener = try!(net::TcpListener::bind(config.addr));
            let local_addr = try!(listener.local_addr());
            (listener, local_addr)
        };

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are pushed in the messages queue
        let messages = MessagesQueue::with_capacity(8);

        let inside_close_trigger = close_trigger.clone();
        let inside_messages = messages.clone();
        thread::spawn(move || {
            // a tasks pool is used to dispatch the connections into threads
            let tasks_pool = util::TaskPool::new();

            loop {
                let new_client = server.accept().map(|(sock, _)| {
                    use util::RefinedTcpStream;

                    let (read_closable, write_closable) = RefinedTcpStream::new(sock);
                    ClientConnection::new(write_closable, read_closable)
                });

                match new_client {
                    Ok(client) => {
                        let messages = inside_messages.clone();
                        let mut client = Some(client);
                        tasks_pool.spawn(Box::new(move || {
                            if let Some(client) = client.take() {
                                for rq in client {
                                    messages.push(rq.into());
                                }
                            }
                        }));
                    },

                    Err(e) => {
                        inside_messages.push(e.into());
                        break;
                    }
                }
            }
        });

        // result
        Ok(Server {
            messages: messages,
            close: close_trigger,
            listening_addr: local_addr,
        })
    }

    /// Returns an iterator for all the incoming requests.
    ///
    /// The iterator will return `None` if the server socket is shutdown.
    #[inline]
    pub fn incoming_requests(&self) -> IncomingRequests {
        IncomingRequests { server: self }
    }

    /// Returns the address the server is listening to.
    #[inline]
    pub fn server_addr(&self) -> net::SocketAddr {
        self.listening_addr.clone()
    }

    /// Returns the number of clients currently connected to the server.
    pub fn num_connections(&self) -> usize {
        unimplemented!()
        //self.requests_receiver.lock().len()
    }

    /// Blocks until an HTTP request has been submitted and returns it.
    pub fn recv(&self) -> IoResult<Request> {
        loop {
            match self.messages.pop() {
                Message::Error(err) => return Err(err),
                Message::NewRequest(rq) => return Ok(rq),
            }
        }
    }

    /// Same as `recv()` but doesn't block.
    pub fn try_recv(&self) -> IoResult<Option<Request>> {
        loop {
            match self.messages.try_pop() {
                Some(Message::Error(err)) => return Err(err),
                Some(Message::NewRequest(rq)) => return Ok(Some(rq)),
                None => return Ok(None)
            }
        }
    }
}

impl<'a> Iterator for IncomingRequests<'a> {
    type Item = Request;
    fn next(&mut self) -> Option<Request> {
        self.server.recv().ok()
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        use std::sync::atomic::Ordering::Relaxed;
        self.close.store(true, Relaxed);
    }
}
<commit_msg>Create an SSL socket if necessary<commit_after>// Copyright 2015 The tiny-http Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*!
# Simple usage

## Creating the server

The easiest way to create a server is to call `Server::http()`.

The `http()` function returns an `IoResult<Server>` which will return an error
in the case where the server creation fails (for example if the listening port is already
occupied).

```no_run
let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
```

A newly-created `Server` will immediatly start listening for incoming connections and HTTP
requests.

## Receiving requests

Calling `server.recv()` will block until the next request is available.
This function returns an `IoResult<Request>`, so you need to handle the possible errors.

```no_run
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();

loop {
    // blocks until the next request is received
    let request = match server.recv() {
        Ok(rq) => rq,
        Err(e) => { println!("error: {}", e); break }
    };

    // do something with the request
    // ...
}
```

In a real-case scenario, you will probably want to spawn multiple worker tasks and call
`server.recv()` on all of them. Like this:

```no_run
# use std::sync::Arc;
# use std::thread;
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
let server = Arc::new(server);
let mut guards = Vec::with_capacity(4);

for _ in (0 .. 4) {
    let server = server.clone();

    let guard = thread::spawn(move || {
        loop {
            let rq = server.recv().unwrap();

            // ...
        }
    });

    guards.push(guard);
}
```

If you don't want to block, you can call `server.try_recv()` instead.

## Handling requests

The `Request` object returned by `server.recv()` contains informations about the client's request.
The most useful methods are probably `request.method()` and `request.url()` which return
the requested method (`GET`, `POST`, etc.) and url.

To handle a request, you need to create a `Response` object. See the docs of this object for
more infos. Here is an example of creating a `Response` from a file:

```no_run
# use std::fs::File;
# use std::path::Path;
let response = tiny_http::Response::from_file(File::open(&Path::new("image.png")).unwrap());
```

All that remains to do is call `request.respond()`:

```no_run
# use std::fs::File;
# use std::path::Path;
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
# let request = server.recv().unwrap();
# let response = tiny_http::Response::from_file(File::open(&Path::new("image.png")).unwrap());
request.respond(response)
```
*/
#![crate_name = "tiny_http"]
#![crate_type = "lib"]
#![forbid(unsafe_code)]

extern crate ascii;
extern crate chunked_transfer;
extern crate encoding;
extern crate url;
extern crate chrono;

#[cfg(feature = "ssl")]
extern crate openssl;

use std::io::Error as IoError;
use std::io::Result as IoResult;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::thread;
use std::net;
use std::net::ToSocketAddrs;

use client::ClientConnection;
use util::MessagesQueue;

pub use common::{Header, HeaderField, HTTPVersion, Method, StatusCode};
pub use request::Request;
pub use response::{ResponseBox, Response};

mod client;
mod common;
mod request;
mod response;

#[allow(dead_code)]     // TODO: remove when everything is implemented
mod util;

/// The main class of this library.
///
/// Destroying this object will immediatly close the listening socket annd the reading
///  part of all the client's connections. Requests that have already been returned by
///  the `recv()` function will not close and the responses will be transferred to the client.
pub struct Server {
    // should be false as long as the server exists
    // when set to true, all the subtasks will close within a few hundreds ms
    close: Arc<AtomicBool>,

    // queue for messages received by child threads
    messages: Arc<MessagesQueue<Message>>,

    // result of TcpListener::local_addr()
    listening_addr: net::SocketAddr,
}

enum Message {
    Error(IoError),
    NewRequest(Request),
}

impl From<IoError> for Message {
    fn from(e: IoError) -> Message {
        Message::Error(e)
    }
}

impl From<Request> for Message {
    fn from(rq: Request) -> Message {
        Message::NewRequest(rq)
    }
}

// this trait is to make sure that Server implements Share and Send
#[doc(hidden)]
trait MustBeShareDummy : Sync + Send {}
#[doc(hidden)]
impl MustBeShareDummy for Server {}

pub struct IncomingRequests<'a> {
    server: &'a Server
}

/// Represents the parameters required to create a server.
#[derive(Debug, Clone)]
pub struct ServerConfig<A> where A: ToSocketAddrs {
    /// The addresses to listen to.
    pub addr: A,
}

impl Server {
    /// Shortcut for a simple server on a specific address.
    #[inline]
    pub fn http<A>(addr: A) -> IoResult<Server>
        where A: ToSocketAddrs
    {
        Server::new(ServerConfig {
            addr: addr,
        })
    }

    /// Builds a new server that listens on the specified address.
    pub fn new<A>(config: ServerConfig<A>) -> IoResult<Server>
        where A: ToSocketAddrs
    {
        // building the "close" variable
        let close_trigger = Arc::new(AtomicBool::new(false));

        // building the TcpListener
        let (server, local_addr) = {
            let listener = try!(net::TcpListener::bind(config.addr));
            let local_addr = try!(listener.local_addr());
            (listener, local_addr)
        };

        // building the SSL capabilities
        #[cfg(feature = "ssl")]
        type SslContext = openssl::ssl::SslContext;
        #[cfg(not(feature = "ssl"))]
        type SslContext = ();
        let ssl: Option<SslContext> = None;     // TODO: implement creating the SSL stuff here

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are pushed in the messages queue
        let messages = MessagesQueue::with_capacity(8);

        let inside_close_trigger = close_trigger.clone();
        let inside_messages = messages.clone();
        thread::spawn(move || {
            // a tasks pool is used to dispatch the connections into threads
            let tasks_pool = util::TaskPool::new();

            loop {
                let new_client = server.accept().map(|(sock, _)| {
                    use util::RefinedTcpStream;

                    let (read_closable, write_closable) = match ssl {
                        None => RefinedTcpStream::new(sock),
                        #[cfg(feature = "ssl")]
                        Some(ref ssl) => {
                            let sock = openssl::ssl::SslStream::accept(ssl, sock).unwrap();     // FIXME: handle this error
                            RefinedTcpStream::new(sock)
                        },
                        #[cfg(not(feature = "ssl"))]
                        Some(_) => unreachable!(),
                    };

                    ClientConnection::new(write_closable, read_closable)
                });

                match new_client {
                    Ok(client) => {
                        let messages = inside_messages.clone();
                        let mut client = Some(client);
                        tasks_pool.spawn(Box::new(move || {
                            if let Some(client) = client.take() {
                                for rq in client {
                                    messages.push(rq.into());
                                }
                            }
                        }));
                    },

                    Err(e) => {
                        inside_messages.push(e.into());
                        break;
                    }
                }
            }
        });

        // result
        Ok(Server {
            messages: messages,
            close: close_trigger,
            listening_addr: local_addr,
        })
    }

    /// Returns an iterator for all the incoming requests.
    ///
    /// The iterator will return `None` if the server socket is shutdown.
    #[inline]
    pub fn incoming_requests(&self) -> IncomingRequests {
        IncomingRequests { server: self }
    }

    /// Returns the address the server is listening to.
    #[inline]
    pub fn server_addr(&self) -> net::SocketAddr {
        self.listening_addr.clone()
    }

    /// Returns the number of clients currently connected to the server.
    pub fn num_connections(&self) -> usize {
        unimplemented!()
        //self.requests_receiver.lock().len()
    }

    /// Blocks until an HTTP request has been submitted and returns it.
    pub fn recv(&self) -> IoResult<Request> {
        loop {
            match self.messages.pop() {
                Message::Error(err) => return Err(err),
                Message::NewRequest(rq) => return Ok(rq),
            }
        }
    }

    /// Same as `recv()` but doesn't block.
    pub fn try_recv(&self) -> IoResult<Option<Request>> {
        loop {
            match self.messages.try_pop() {
                Some(Message::Error(err)) => return Err(err),
                Some(Message::NewRequest(rq)) => return Ok(Some(rq)),
                None => return Ok(None)
            }
        }
    }
}

impl<'a> Iterator for IncomingRequests<'a> {
    type Item = Request;
    fn next(&mut self) -> Option<Request> {
        self.server.recv().ok()
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        use std::sync::atomic::Ordering::Relaxed;
        self.close.store(true, Relaxed);
    }
}
<|endoftext|>


<commit_before>//! Helpers for writing Alfred XML output

#![warn(missing_doc)]

use std::io;
use std::io::BufferedWriter;
use std::str;

/// Representation of an <item>
#[deriving(PartialEq,Eq,Clone)]
pub struct Item {
    /// Identifier for the results. If given, must be unique among items, and is used for
    /// prioritizing feedback results based on usage. If blank, Alfred uses a UUID and does
    /// not learn from the results.
    pub uid: Option<str::MaybeOwned<'static>>,
    /// The value that is passed to the next portion of the workflow when this item
    /// is selected.
    pub arg: Option<str::MaybeOwned<'static>>,
    /// What type of result this is, if any.
    pub type_: Option<ItemType>,
    /// Whether or not the result item is 'valid'. If `false`, `autocomplete` may be used.
    pub valid: bool,
    /// Autocomplete data for valid=false items. When this item is selected, the autocomplete
    /// value is inserted into the Alfred window.
    pub autocomplete: Option<str::MaybeOwned<'static>>,

    /// Title for the item
    pub title: str::MaybeOwned<'static>,
    /// Subtitle for the item
    pub subtitle: Option<str::MaybeOwned<'static>>,
    /// Icon for the item
    pub icon: Option<Icon>
}

impl Item {
    /// Returns a new Item with the given title
    pub fn new<S: str::IntoMaybeOwned<'static>>(title: S) -> Item {
        Item {
            uid: None,
            arg: None,
            type_: None,
            valid: true,
            autocomplete: None,
            title: title.into_maybe_owned(),
            subtitle: None,
            icon: None
        }
    }
}

/// Item icons
#[deriving(PartialEq,Eq,Clone)]
pub enum Icon {
    /// Path to an image file on disk relative to the workflow directory
    PathIcon(str::MaybeOwned<'static>),
    /// Path to a file whose icon will be used
    FileIcon(str::MaybeOwned<'static>),
    /// UTI for a file type to use (e.g. public.folder)
    FileType(str::MaybeOwned<'static>)
}

/// Item types
#[deriving(PartialEq,Eq,Clone)]
pub enum ItemType {
    /// Type representing a file
    FileItemType
}

impl Item {
    /// Writes the XML fragment representing the Item to the Writer
    pub fn write_xml(&self, w: &mut io::Writer, indent: uint) -> io::IoResult<()> {
        fn write_indent(w: &mut io::Writer, indent: uint) -> io::IoResult<()> {
            for _ in range(0, indent) {
                try!(w.write_str("    "));
            }
            Ok(())
        }

        let mut w = BufferedWriter::with_capacity(512, w);

        try!(write_indent(&mut w, indent));
        try!(w.write_str("<item"));
        match self.uid {
            None => (),
            Some(ref uid) => {
                try!(write!(&mut w, r#" uid="{}""#, encode_entities(uid.as_slice())));
            }
        }
        match self.arg {
            None => (),
            Some(ref arg) => {
                try!(write!(&mut w, r#" arg="{}""#, encode_entities(arg.as_slice())));
            }
        }
        match self.type_ {
            None => (),
            Some(FileItemType) => {
                try!(w.write_str(r#" type="file""#));
            }
        }
        try!(write!(&mut w, r#" valid="{}""#, if self.valid { "yes" } else { "no" }));
        match self.autocomplete {
            None => (),
            Some(ref auto) => {
                try!(write!(&mut w, r#" autocomplete="{}""#, encode_entities(auto.as_slice())));
            }
        }
        try!(w.write_str(">\n"));

        try!(write_indent(&mut w, indent+1));
        try!(write!(&mut w, "<title>{}</title>\n", encode_entities(self.title.as_slice())));

        match self.subtitle {
            None => (),
            Some(ref s) => {
                try!(write_indent(&mut w, indent+1));
                try!(write!(&mut w, "<subtitle>{}</subtitle>\n", encode_entities(s.as_slice())));
            }
        }

        match self.icon {
            None => (),
            Some(ref icon) => {
                try!(write_indent(&mut w, indent+1));
                match *icon {
                    PathIcon(ref s) => {
                        try!(write!(&mut w, "<icon>{}</icon>\n", encode_entities(s.as_slice())));
                    }
                    FileIcon(ref s) => {
                        try!(write!(&mut w, "<icon type=\"fileicon\">{}</icon>\n",
                                      encode_entities(s.as_slice())));
                    }
                    FileType(ref s) => {
                        try!(write!(&mut w, "<icon type=\"filetype\">{}</icon>\n",
                                      encode_entities(s.as_slice())));
                    }
                }
            }
        }

        try!(write_indent(&mut w, indent));
        try!(w.write_str("</item>\n"));

        try!(w.flush());
        Ok(())
    }
}

fn encode_entities<'a>(s: &'a str) -> str::MaybeOwned<'a> {
    fn encode_entity(c: char) -> Option<&'static str> {
        Some(match c {
            '<' => "<",
            '>' => ">",
            '"' => """,
            '&' => "&",
            '\0'...'\x08' |
            '\x0B'...'\x0C' |
            '\x0E'...'\x1F' |
            '\uFFFE' | '\uFFFF' => {
                // these are all invalid characters in XML
                "\uFFFD"
            }
            _ => return None
        })
    }

    if s.chars().any(|c| encode_entity(c).is_some()) {
        let mut res = String::with_capacity(s.len());
        for c in s.chars() {
            match encode_entity(c) {
                Some(ent) => res.push_str(ent),
                None => res.push(c)
            }
        }
        str::Owned(res)
    } else {
        str::Slice(s)
    }
}
<commit_msg>Fix docstring for Item<commit_after>//! Helpers for writing Alfred XML output

#![warn(missing_doc)]

use std::io;
use std::io::BufferedWriter;
use std::str;

/// Representation of an `<item>`
#[deriving(PartialEq,Eq,Clone)]
pub struct Item {
    /// Identifier for the results. If given, must be unique among items, and is used for
    /// prioritizing feedback results based on usage. If blank, Alfred uses a UUID and does
    /// not learn from the results.
    pub uid: Option<str::MaybeOwned<'static>>,
    /// The value that is passed to the next portion of the workflow when this item
    /// is selected.
    pub arg: Option<str::MaybeOwned<'static>>,
    /// What type of result this is, if any.
    pub type_: Option<ItemType>,
    /// Whether or not the result item is 'valid'. If `false`, `autocomplete` may be used.
    pub valid: bool,
    /// Autocomplete data for valid=false items. When this item is selected, the autocomplete
    /// value is inserted into the Alfred window.
    pub autocomplete: Option<str::MaybeOwned<'static>>,

    /// Title for the item
    pub title: str::MaybeOwned<'static>,
    /// Subtitle for the item
    pub subtitle: Option<str::MaybeOwned<'static>>,
    /// Icon for the item
    pub icon: Option<Icon>
}

impl Item {
    /// Returns a new Item with the given title
    pub fn new<S: str::IntoMaybeOwned<'static>>(title: S) -> Item {
        Item {
            uid: None,
            arg: None,
            type_: None,
            valid: true,
            autocomplete: None,
            title: title.into_maybe_owned(),
            subtitle: None,
            icon: None
        }
    }
}

/// Item icons
#[deriving(PartialEq,Eq,Clone)]
pub enum Icon {
    /// Path to an image file on disk relative to the workflow directory
    PathIcon(str::MaybeOwned<'static>),
    /// Path to a file whose icon will be used
    FileIcon(str::MaybeOwned<'static>),
    /// UTI for a file type to use (e.g. public.folder)
    FileType(str::MaybeOwned<'static>)
}

/// Item types
#[deriving(PartialEq,Eq,Clone)]
pub enum ItemType {
    /// Type representing a file
    FileItemType
}

impl Item {
    /// Writes the XML fragment representing the Item to the Writer
    pub fn write_xml(&self, w: &mut io::Writer, indent: uint) -> io::IoResult<()> {
        fn write_indent(w: &mut io::Writer, indent: uint) -> io::IoResult<()> {
            for _ in range(0, indent) {
                try!(w.write_str("    "));
            }
            Ok(())
        }

        let mut w = BufferedWriter::with_capacity(512, w);

        try!(write_indent(&mut w, indent));
        try!(w.write_str("<item"));
        match self.uid {
            None => (),
            Some(ref uid) => {
                try!(write!(&mut w, r#" uid="{}""#, encode_entities(uid.as_slice())));
            }
        }
        match self.arg {
            None => (),
            Some(ref arg) => {
                try!(write!(&mut w, r#" arg="{}""#, encode_entities(arg.as_slice())));
            }
        }
        match self.type_ {
            None => (),
            Some(FileItemType) => {
                try!(w.write_str(r#" type="file""#));
            }
        }
        try!(write!(&mut w, r#" valid="{}""#, if self.valid { "yes" } else { "no" }));
        match self.autocomplete {
            None => (),
            Some(ref auto) => {
                try!(write!(&mut w, r#" autocomplete="{}""#, encode_entities(auto.as_slice())));
            }
        }
        try!(w.write_str(">\n"));

        try!(write_indent(&mut w, indent+1));
        try!(write!(&mut w, "<title>{}</title>\n", encode_entities(self.title.as_slice())));

        match self.subtitle {
            None => (),
            Some(ref s) => {
                try!(write_indent(&mut w, indent+1));
                try!(write!(&mut w, "<subtitle>{}</subtitle>\n", encode_entities(s.as_slice())));
            }
        }

        match self.icon {
            None => (),
            Some(ref icon) => {
                try!(write_indent(&mut w, indent+1));
                match *icon {
                    PathIcon(ref s) => {
                        try!(write!(&mut w, "<icon>{}</icon>\n", encode_entities(s.as_slice())));
                    }
                    FileIcon(ref s) => {
                        try!(write!(&mut w, "<icon type=\"fileicon\">{}</icon>\n",
                                      encode_entities(s.as_slice())));
                    }
                    FileType(ref s) => {
                        try!(write!(&mut w, "<icon type=\"filetype\">{}</icon>\n",
                                      encode_entities(s.as_slice())));
                    }
                }
            }
        }

        try!(write_indent(&mut w, indent));
        try!(w.write_str("</item>\n"));

        try!(w.flush());
        Ok(())
    }
}

fn encode_entities<'a>(s: &'a str) -> str::MaybeOwned<'a> {
    fn encode_entity(c: char) -> Option<&'static str> {
        Some(match c {
            '<' => "<",
            '>' => ">",
            '"' => """,
            '&' => "&",
            '\0'...'\x08' |
            '\x0B'...'\x0C' |
            '\x0E'...'\x1F' |
            '\uFFFE' | '\uFFFF' => {
                // these are all invalid characters in XML
                "\uFFFD"
            }
            _ => return None
        })
    }

    if s.chars().any(|c| encode_entity(c).is_some()) {
        let mut res = String::with_capacity(s.len());
        for c in s.chars() {
            match encode_entity(c) {
                Some(ent) => res.push_str(ent),
                None => res.push(c)
            }
        }
        str::Owned(res)
    } else {
        str::Slice(s)
    }
}
<|endoftext|>


<commit_before>#![allow(clippy::non_ascii_literal)]

#[macro_use]
extern crate seed;

use seed::prelude::*;

pub mod pages;
pub mod utils;

#[derive(Copy, Clone)]
pub enum Page {
    ContactUs,
    Downloads,
    Faq,
    Home,
    Status,
    FermatArchive,
    FibonacciArchive,
    MersenneArchive,
    PerfectArchive,
    PrimalityChecker,
    PrimeNumbersArchive,
    NumberCruncher,
}

// Model
struct Model {
    page: Page,
    slug: std::string::String,
}

// Setup a default here, for initialization later.
impl Default for Model {
    fn default() -> Self {
        Self {
            page: Page::Home,
            slug: "".to_owned(),
        }
    }
}

// Update
#[derive(Clone)]
pub enum Msg {
    ChangePage(Page, std::string::String),
}

/// The sole source of updating the model
fn update(msg: Msg, model: &mut Model, _: &mut impl Orders<Msg>) {
    match msg {
        Msg::ChangePage(page, slug) => {model.page = page; model.slug = slug}
    }
}

/// The top-level component we pass to the virtual dom. Must accept the model as its
/// only argument, and output has to implement trait `ElContainer`.
fn view(model: &Model) -> impl View<Msg> {
    match model.page {
        Page::ContactUs => pages::contact::render(),
        Page::Downloads => pages::downloads::render(),
        Page::Faq => pages::faq::render(),
        Page::FermatArchive => pages::archive::fermat::render(),
        Page::FibonacciArchive => pages::archive::fibonacci::render(model.slug.to_owned()),
        Page::Home => pages::home::render(),
        Page::MersenneArchive => pages::archive::mersenne::render(),
        Page::NumberCruncher => pages::cruncher::render(model.slug.to_owned()),
        Page::PerfectArchive => pages::archive::perfect::render(),
        Page::PrimalityChecker => pages::primalitytest::render(),
        Page::PrimeNumbersArchive => pages::archive::prime::render(model.slug.to_owned()),
        Page::Status => pages::status::render(),
    }
}

impl ToString for Page {
    fn to_string(&self) -> String {
        // Eg for url routing
        match self {
            Page::ContactUs => "contactus".into(),
            Page::Downloads => "downloads".into(),
            Page::Faq => "faq".into(),
            Page::FermatArchive => "fermat".into(),
            Page::FibonacciArchive => "fibonacci".into(),//TODO: check this is right, might need the archive/ prefix!
            Page::Home => "home".into(),
            Page::Status => "status".into(),
            Page::MersenneArchive => "mersenne".into(),
            Page::NumberCruncher => "cruncher".into(),
            Page::PerfectArchive => "perfect".into(),
            Page::PrimalityChecker => "primalitytest".into(),
            Page::PrimeNumbersArchive => "primes".into(),//TODO: check this is right, might need the archive/ prefix!
        }
    }
}

fn routes(url: seed::Url) -> Msg {

    let empty_string = "".to_owned();

    if url.path.is_empty() {
        return Msg::ChangePage(Page::Home, empty_string)
    }

    match url.path[0].as_ref() {
        "archive" => {
            // Determine if we are at the archive page, or a subpage
            match url.path[1].as_ref() {
                "fermat" => Msg::ChangePage(Page::FermatArchive, empty_string),
                "fibonacci" => {
                    match url.path.get(2).as_ref() {
                        Some(_slug) => Msg::ChangePage(Page::FibonacciArchive, url.path[2].to_owned()),
                        None => Msg::ChangePage(Page::FibonacciArchive, "1".to_owned()),
                    }
                },
                "mersenne" => Msg::ChangePage(Page::MersenneArchive, empty_string),
                "perfect" => Msg::ChangePage(Page::PerfectArchive, empty_string),
                "prime" => {
                    match url.path.get(2).as_ref() {
                        Some(_slug) => Msg::ChangePage(Page::PrimeNumbersArchive, url.path[2].to_owned()),
                        None => Msg::ChangePage(Page::PrimeNumbersArchive, "1".to_owned()),
                    }
                },
                _ => Msg::ChangePage(Page::Home, empty_string)//TODO: add archive page
            }
        },
        "contactus" => Msg::ChangePage(Page::ContactUs, empty_string),
        "cruncher" => {
            match url.path.get(1).as_ref() {
                Some(_slug) => Msg::ChangePage(Page::NumberCruncher, url.path[1].to_owned()),
                None => Msg::ChangePage(Page::NumberCruncher, empty_string),
            }
        },
        "downloads" => Msg::ChangePage(Page::Downloads, empty_string),
        "faq" => Msg::ChangePage(Page::Faq, empty_string),
        "primalitytest" => Msg::ChangePage(Page::PrimalityChecker, empty_string),
        "status" => Msg::ChangePage(Page::Status, empty_string),
        _ => Msg::ChangePage(Page::Home, empty_string)
    }
}

#[wasm_bindgen(start)]
pub fn render() {
    seed::App::build(init, update, view)
        .mount("app")
        .routes(routes)
        //.window_events(window_events)
        .finish()
        .run();
}

fn init(url: Url, orders: &mut impl Orders<Msg>) -> Model {
    let mut model = Model::default();
    update(routes(url), &mut model, orders);
    model
}<commit_msg>Model struct is now public<commit_after>#![allow(clippy::non_ascii_literal)]

#[macro_use]
extern crate seed;

use seed::prelude::*;

pub mod pages;
pub mod utils;

#[derive(Copy, Clone)]
pub enum Page {
    ContactUs,
    Downloads,
    Faq,
    Home,
    Status,
    FermatArchive,
    FibonacciArchive,
    MersenneArchive,
    PerfectArchive,
    PrimalityChecker,
    PrimeNumbersArchive,
    NumberCruncher,
}

// Model
pub struct Model {
    download: std::string::String,
    page: Page,
    slug: std::string::String,
}

// Setup a default here, for initialization later.
impl Default for Model {
    fn default() -> Self {
        Self {
            page: Page::Home,
            slug: "".to_owned(),
        }
    }
}

// Update
#[derive(Clone)]
pub enum Msg {
    ChangePage(Page, std::string::String),
}

/// The sole source of updating the model
fn update(msg: Msg, model: &mut Model, _: &mut impl Orders<Msg>) {
    match msg {
        Msg::ChangePage(page, slug) => {model.page = page; model.slug = slug}
    }
}

/// The top-level component we pass to the virtual dom. Must accept the model as its
/// only argument, and output has to implement trait `ElContainer`.
fn view(model: &Model) -> impl View<Msg> {
    match model.page {
        Page::ContactUs => pages::contact::render(),
        Page::Downloads => pages::downloads::render(),
        Page::Faq => pages::faq::render(),
        Page::FermatArchive => pages::archive::fermat::render(),
        Page::FibonacciArchive => pages::archive::fibonacci::render(model.slug.to_owned()),
        Page::Home => pages::home::render(),
        Page::MersenneArchive => pages::archive::mersenne::render(),
        Page::NumberCruncher => pages::cruncher::render(model.slug.to_owned()),
        Page::PerfectArchive => pages::archive::perfect::render(),
        Page::PrimalityChecker => pages::primalitytest::render(),
        Page::PrimeNumbersArchive => pages::archive::prime::render(model.slug.to_owned()),
        Page::Status => pages::status::render(),
    }
}

impl ToString for Page {
    fn to_string(&self) -> String {
        // Eg for url routing
        match self {
            Page::ContactUs => "contactus".into(),
            Page::Downloads => "downloads".into(),
            Page::Faq => "faq".into(),
            Page::FermatArchive => "fermat".into(),
            Page::FibonacciArchive => "fibonacci".into(),//TODO: check this is right, might need the archive/ prefix!
            Page::Home => "home".into(),
            Page::Status => "status".into(),
            Page::MersenneArchive => "mersenne".into(),
            Page::NumberCruncher => "cruncher".into(),
            Page::PerfectArchive => "perfect".into(),
            Page::PrimalityChecker => "primalitytest".into(),
            Page::PrimeNumbersArchive => "primes".into(),//TODO: check this is right, might need the archive/ prefix!
        }
    }
}

fn routes(url: seed::Url) -> Msg {

    let empty_string = "".to_owned();

    if url.path.is_empty() {
        return Msg::ChangePage(Page::Home, empty_string)
    }

    match url.path[0].as_ref() {
        "archive" => {
            // Determine if we are at the archive page, or a subpage
            match url.path[1].as_ref() {
                "fermat" => Msg::ChangePage(Page::FermatArchive, empty_string),
                "fibonacci" => {
                    match url.path.get(2).as_ref() {
                        Some(_slug) => Msg::ChangePage(Page::FibonacciArchive, url.path[2].to_owned()),
                        None => Msg::ChangePage(Page::FibonacciArchive, "1".to_owned()),
                    }
                },
                "mersenne" => Msg::ChangePage(Page::MersenneArchive, empty_string),
                "perfect" => Msg::ChangePage(Page::PerfectArchive, empty_string),
                "prime" => {
                    match url.path.get(2).as_ref() {
                        Some(_slug) => Msg::ChangePage(Page::PrimeNumbersArchive, url.path[2].to_owned()),
                        None => Msg::ChangePage(Page::PrimeNumbersArchive, "1".to_owned()),
                    }
                },
                _ => Msg::ChangePage(Page::Home, empty_string)//TODO: add archive page
            }
        },
        "contactus" => Msg::ChangePage(Page::ContactUs, empty_string),
        "cruncher" => {
            match url.path.get(1).as_ref() {
                Some(_slug) => Msg::ChangePage(Page::NumberCruncher, url.path[1].to_owned()),
                None => Msg::ChangePage(Page::NumberCruncher, empty_string),
            }
        },
        "downloads" => Msg::ChangePage(Page::Downloads, empty_string),
        "faq" => Msg::ChangePage(Page::Faq, empty_string),
        "primalitytest" => Msg::ChangePage(Page::PrimalityChecker, empty_string),
        "status" => Msg::ChangePage(Page::Status, empty_string),
        _ => Msg::ChangePage(Page::Home, empty_string)
    }
}

#[wasm_bindgen(start)]
pub fn render() {
    seed::App::build(init, update, view)
        .mount("app")
        .routes(routes)
        //.window_events(window_events)
        .finish()
        .run();
}

fn init(url: Url, orders: &mut impl Orders<Msg>) -> Model {
    let mut model = Model::default();
    update(routes(url), &mut model, orders);
    model
}<|endoftext|>


<commit_before>#![crate_name = "logger"]
#![license = "MIT"]

//! Request logging middleware for Iron

#[deny(warnings)]

extern crate iron;
extern crate http;
extern crate time;
extern crate term;
extern crate typemap;

use iron::{AfterMiddleware, BeforeMiddleware, IronResult, Request, Response};
use typemap::Assoc;
use time::precise_time_ns;
use term::{Terminal, WriterWrapper, stdout};

use std::io::IoResult;

use format::{Format, FormatText, Str, Method, URI, Status, ResponseTime,
             ConstantColor, FunctionColor, ConstantAttrs, FunctionAttrs};

pub mod format;

/// `Middleware` for logging request and response info to the terminal.
pub struct Logger {
    format: Option<Format>
}

impl Logger {
    /// Create a pair of `Logger` middlewares with the specified `format`. If a `None` is passed in, uses the default format:
    ///
    /// ```ignore
    /// {method} {uri} -> {status} ({response_time} ms)
    /// ```
    ///
    /// While the returned value can be passed straight to `Chain::link`, consider making the logger `BeforeMiddleware`
    /// the first in your chain and the logger `AfterMiddleware` the last by doing something like this:
    ///
    /// ```ignore
    /// let mut chain = ChainBuilder::new(handler);
    /// let (logger_before, logger_after) = Logger::new(None);
    /// chain.link_before(logger_before);
    /// // link other middlewares here...
    /// chain.link_after(logger_after);
    /// ```
    pub fn new(format: Option<Format>) -> (Logger, Logger) {
        (Logger { format: format.clone() }, Logger { format: format })
    }
}

struct StartTime;
impl Assoc<u64> for StartTime {}

impl BeforeMiddleware for Logger {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        req.extensions.insert::<StartTime, u64>(precise_time_ns());
        Ok(())
    }
}

impl AfterMiddleware for Logger {
    fn after(&self, req: &mut Request, res: &mut Response) -> IronResult<()> {
        let entry_time = *req.extensions.find::<StartTime, u64>().unwrap();
        let response_time_ms = (precise_time_ns() - entry_time) as f64 / 1000000.0;
        let Format(format) = self.format.clone().unwrap_or_default();

        let render = |text: &FormatText| {
            match *text {
                Str(ref string) => string.clone(),
                Method => format!("{}", req.method),
                URI => format!("{}", req.url),
                Status => format!("{}", res.status),
                ResponseTime => format!("{} ms", response_time_ms)
            }
        };
        let log = |mut t: Box<Terminal<WriterWrapper> + Send>| -> IoResult<()> {
            for unit in format.iter() {
                match unit.color {
                    ConstantColor(Some(color)) => { try!(t.fg(color)); }
                    ConstantColor(None) => (),
                    FunctionColor(f) => match f(req, res) {
                        Some(color) => { try!(t.fg(color)); }
                        None => ()
                    }
                }
                match unit.attrs {
                    ConstantAttrs(ref attrs) => {
                        for &attr in attrs.iter() {
                            try!(t.attr(attr));
                        }
                    }
                    FunctionAttrs(f) => {
                        for &attr in f(req, res).iter() {
                            try!(t.attr(attr));
                        }
                    }
                }
                try!(write!(t, "{}", render(&unit.text)));
                try!(t.reset());
            }
            try!(writeln!(t, ""));
            Ok(())
        };

        match stdout() {
            Some(terminal) => {
                match log(terminal) {
                    Err(e) => { println!("Error logging to terminal: {}", e); },
                    Ok(_) => ()
                }
            }
            None => { println!("Logger could not open terminal"); }
        }
        Ok(())
    }
}
<commit_msg>(refactor) Use Errors instead of printing on failure.<commit_after>#![crate_name = "logger"]
#![license = "MIT"]

//! Request logging middleware for Iron

#[deny(warnings)]

extern crate iron;
extern crate http;
extern crate time;
extern crate term;
extern crate typemap;

use iron::{AfterMiddleware, BeforeMiddleware, IronResult, Request, Response, Error};
use iron::errors::FileError;
use iron::typemap::Assoc;
use term::{Terminal, WriterWrapper, stdout};

use std::io::IoResult;

use format::{Format, FormatText, Str, Method, URI, Status, ResponseTime,
             ConstantColor, FunctionColor, ConstantAttrs, FunctionAttrs};

pub mod format;

/// `Middleware` for logging request and response info to the terminal.
pub struct Logger {
    format: Option<Format>
}

impl Logger {
    /// Create a pair of `Logger` middlewares with the specified `format`. If a `None` is passed in, uses the default format:
    ///
    /// ```ignore
    /// {method} {uri} -> {status} ({response_time} ms)
    /// ```
    ///
    /// While the returned value can be passed straight to `Chain::link`, consider making the logger `BeforeMiddleware`
    /// the first in your chain and the logger `AfterMiddleware` the last by doing something like this:
    ///
    /// ```ignore
    /// let mut chain = ChainBuilder::new(handler);
    /// let (logger_before, logger_after) = Logger::new(None);
    /// chain.link_before(logger_before);
    /// // link other middlewares here...
    /// chain.link_after(logger_after);
    /// ```
    pub fn new(format: Option<Format>) -> (Logger, Logger) {
        (Logger { format: format.clone() }, Logger { format: format })
    }
}

struct StartTime;
impl Assoc<u64> for StartTime {}

impl BeforeMiddleware for Logger {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        req.extensions.insert::<StartTime, u64>(time::precise_time_ns());
        Ok(())
    }
}

impl AfterMiddleware for Logger {
    fn after(&self, req: &mut Request, res: &mut Response) -> IronResult<()> {
        let entry_time = *req.extensions.find::<StartTime, u64>().unwrap();
        let response_time_ms = (time::precise_time_ns() - entry_time) as f64 / 1000000.0;
        let Format(format) = self.format.clone().unwrap_or_default();

        let render = |text: &FormatText| {
            match *text {
                Str(ref string) => string.clone(),
                Method => format!("{}", req.method),
                URI => format!("{}", req.url),
                Status => format!("{}", res.status),
                ResponseTime => format!("{} ms", response_time_ms)
            }
        };

        let log = |mut t: Box<Terminal<WriterWrapper> + Send>| -> IoResult<()> {
            for unit in format.iter() {
                match unit.color {
                    ConstantColor(Some(color)) => { try!(t.fg(color)); }
                    ConstantColor(None) => (),
                    FunctionColor(f) => match f(req, res) {
                        Some(color) => { try!(t.fg(color)); }
                        None => ()
                    }
                }
                match unit.attrs {
                    ConstantAttrs(ref attrs) => {
                        for &attr in attrs.iter() {
                            try!(t.attr(attr));
                        }
                    }
                    FunctionAttrs(f) => {
                        for &attr in f(req, res).iter() {
                            try!(t.attr(attr));
                        }
                    }
                }
                try!(write!(t, "{}", render(&unit.text)));
                try!(t.reset());
            }
            try!(writeln!(t, ""));
            Ok(())
        };

        match stdout() {
            Some(terminal) => {
                match log(terminal) {
                    Err(e) => return Err(FileError(e).erase()),
                    _ => {}
                }
            }
            None => { return Err(CouldNotOpenTerminal.erase()) }
        };

        Ok(())
    }
}

/// Error returned when logger cannout access stdout.
#[deriving(Show)]
pub struct CouldNotOpenTerminal;

impl Error for CouldNotOpenTerminal {
    fn name(&self) -> &'static str {
        "Could Not Open Terminal"
    }

    fn description(&self) -> Option<&str> {
        Some("Logger could not open stdout as a terminal.")
    }
}

<|endoftext|>