<commit_before>// Copyright 2017 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.

// ignore-cross-compile

#![feature(rustc_private)]

extern crate syntax;

use syntax::ast::*;
use syntax::codemap::{Spanned, DUMMY_SP};
use syntax::codemap::FilePathMapping;
use syntax::fold::{self, Folder};
use syntax::parse::{self, ParseSess};
use syntax::print::pprust;
use syntax::ptr::P;
use syntax::util::ThinVec;

fn parse_expr(ps: &ParseSess, src: &str) -> P<Expr> {
    let mut p = parse::new_parser_from_source_str(ps,
                                                  "<expr>".to_owned(),
                                                  src.to_owned());
    p.parse_expr().unwrap()
}

// Helper functions for building exprs
fn expr(kind: ExprKind) -> P<Expr> {
    P(Expr {
        id: DUMMY_NODE_ID,
        node: kind,
        span: DUMMY_SP,
        attrs: ThinVec::new(),
    })
}

fn make_x() -> P<Expr> {
    let seg = PathSegment {
        identifier: Ident::from_str("x"),
        span: DUMMY_SP,
        parameters: None,
    };
    let path = Path {
        span: DUMMY_SP,
        segments: vec![seg],
    };
    expr(ExprKind::Path(None, path))
}

/// Iterate over exprs of depth up to `depth`.  The goal is to explore all "interesting"
/// combinations of expression nesting.  For example, we explore combinations using `if`, but not
/// `while` or `match`, since those should print and parse in much the same way as `if`.
fn iter_exprs(depth: usize, f: &mut FnMut(P<Expr>)) {
    if depth == 0 {
        f(make_x());
        return;
    }

    let mut g = |e| f(expr(e));

    for kind in 0 .. 17 {
        match kind {
            0 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Box(e))),
            1 => {
                // Note that for binary expressions, we explore each side separately.  The
                // parenthesization decisions for the LHS and RHS should be independent, and this
                // way produces `O(n)` results instead of `O(n^2)`.
                iter_exprs(depth - 1, &mut |e| g(ExprKind::InPlace(e, make_x())));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::InPlace(make_x(), e)));
            },
            2 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Call(e, vec![]))),
            3 => {
                let seg = PathSegment {
                    identifier: Ident::from_str("x"),
                    span: DUMMY_SP,
                    parameters: None,
                };

                iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall(
                            seg.clone(), vec![e, make_x()])));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall(
                            seg.clone(), vec![make_x(), e])));
            },
            4 => {
                let op = Spanned { span: DUMMY_SP, node: BinOpKind::Add };
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, e, make_x())));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, make_x(), e)));
            },
            5 => {
                let op = Spanned { span: DUMMY_SP, node: BinOpKind::Mul };
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, e, make_x())));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, make_x(), e)));
            },
            6 => {
                let op = Spanned { span: DUMMY_SP, node: BinOpKind::Shl };
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, e, make_x())));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, make_x(), e)));
            },
            7 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Unary(UnOp::Deref, e)));
            },
            8 => {
                let block = P(Block {
                    stmts: Vec::new(),
                    id: DUMMY_NODE_ID,
                    rules: BlockCheckMode::Default,
                    span: DUMMY_SP,
                });
                iter_exprs(depth - 1, &mut |e| g(ExprKind::If(e, block.clone(), None)));
            },
            9 => {
                let decl = P(FnDecl {
                    inputs: vec![],
                    output: FunctionRetTy::Default(DUMMY_SP),
                    variadic: false,
                });
                iter_exprs(depth - 1, &mut |e| g(
                        ExprKind::Closure(CaptureBy::Value, decl.clone(), e, DUMMY_SP)));
            },
            10 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Assign(e, make_x())));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Assign(make_x(), e)));
            },
            11 => {
                let ident = Spanned { span: DUMMY_SP, node: Ident::from_str("f") };
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Field(e, ident)));
            },
            12 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Range(
                            Some(e), Some(make_x()), RangeLimits::HalfOpen)));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Range(
                            Some(make_x()), Some(e), RangeLimits::HalfOpen)));
            },
            13 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::AddrOf(Mutability::Immutable, e)));
            },
            14 => {
                g(ExprKind::Ret(None));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Ret(Some(e))));
            },
            15 => {
                let seg = PathSegment {
                    identifier: Ident::from_str("S"),
                    span: DUMMY_SP,
                    parameters: None,
                };
                let path = Path {
                    span: DUMMY_SP,
                    segments: vec![seg],
                };
                g(ExprKind::Struct(path, vec![], Some(make_x())));
            },
            16 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Try(e)));
            },
            _ => panic!("bad counter value in iter_exprs"),
        }
    }
}

// Folders for manipulating the placement of `Paren` nodes.  See below for why this is needed.

/// Folder that removes all `ExprKind::Paren` nodes.
struct RemoveParens;

impl Folder for RemoveParens {
    fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
        let e = match e.node {
            ExprKind::Paren(ref inner) => inner.clone(),
            _ => e.clone(),
        };
        e.map(|e| fold::noop_fold_expr(e, self))
    }
}

/// Folder that inserts `ExprKind::Paren` nodes around every `Expr`.
struct AddParens;

impl Folder for AddParens {
    fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
        let e = e.map(|e| fold::noop_fold_expr(e, self));
        P(Expr {
            id: DUMMY_NODE_ID,
            node: ExprKind::Paren(e),
            span: DUMMY_SP,
            attrs: ThinVec::new(),
        })
    }
}

fn main() {
    let ps = ParseSess::new(FilePathMapping::empty());

    iter_exprs(2, &mut |e| {
        // If the pretty printer is correct, then `parse(print(e))` should be identical to `e`,
        // modulo placement of `Paren` nodes.
        let printed = pprust::expr_to_string(&e);
        println!("printed: {}", printed);

        let parsed = parse_expr(&ps, &printed);

        // We want to know if `parsed` is structurally identical to `e`, ignoring trivial
        // differences like placement of `Paren`s or the exact ranges of node spans.
        // Unfortunately, there is no easy way to make this comparison.  Instead, we add `Paren`s
        // everywhere we can, then pretty-print.  This should give an unambiguous representation of
        // each `Expr`, and it bypasses nearly all of the parenthesization logic, so we aren't
        // relying on the correctness of the very thing we're testing.
        let e1 = AddParens.fold_expr(RemoveParens.fold_expr(e));
        let text1 = pprust::expr_to_string(&e1);
        let e2 = AddParens.fold_expr(RemoveParens.fold_expr(parsed));
        let text2 = pprust::expr_to_string(&e2);
        assert!(text1 == text2,
                "exprs are not equal:\n  e =      {:?}\n  parsed = {:?}",
                text1, text2);
    });
}
<commit_msg>better explanatory comment for the pprust-expr-roundtrip test<commit_after>// Copyright 2017 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.

// ignore-cross-compile

// The general idea of this test is to enumerate all "interesting" expressions and check that
// `parse(print(e)) == e` for all `e`.  Here's what's interesting, for the purposes of this test:
//
//  1. The test focuses on expression nesting, because interactions between different expression
//     types are harder to test manually than single expression types in isolation.
//
//  2. The test only considers expressions of at most two nontrivial nodes.  So it will check `x +
//     x` and `x + (x - x)` but not `(x * x) + (x - x)`.  The assumption here is that the correct
//     handling of an expression might depend on the expression's parent, but doesn't depend on its
//     siblings or any more distant ancestors.
//
// 3. The test only checks certain expression kinds.  The assumption is that similar expression
//    types, such as `if` and `while` or `+` and `-`,  will be handled identically in the printer
//    and parser.  So if all combinations of exprs involving `if` work correctly, then combinations
//    using `while`, `if let`, and so on will likely work as well.

#![feature(rustc_private)]

extern crate syntax;

use syntax::ast::*;
use syntax::codemap::{Spanned, DUMMY_SP};
use syntax::codemap::FilePathMapping;
use syntax::fold::{self, Folder};
use syntax::parse::{self, ParseSess};
use syntax::print::pprust;
use syntax::ptr::P;
use syntax::util::ThinVec;

fn parse_expr(ps: &ParseSess, src: &str) -> P<Expr> {
    let mut p = parse::new_parser_from_source_str(ps,
                                                  "<expr>".to_owned(),
                                                  src.to_owned());
    p.parse_expr().unwrap()
}

// Helper functions for building exprs
fn expr(kind: ExprKind) -> P<Expr> {
    P(Expr {
        id: DUMMY_NODE_ID,
        node: kind,
        span: DUMMY_SP,
        attrs: ThinVec::new(),
    })
}

fn make_x() -> P<Expr> {
    let seg = PathSegment {
        identifier: Ident::from_str("x"),
        span: DUMMY_SP,
        parameters: None,
    };
    let path = Path {
        span: DUMMY_SP,
        segments: vec![seg],
    };
    expr(ExprKind::Path(None, path))
}

/// Iterate over exprs of depth up to `depth`.  The goal is to explore all "interesting"
/// combinations of expression nesting.  For example, we explore combinations using `if`, but not
/// `while` or `match`, since those should print and parse in much the same way as `if`.
fn iter_exprs(depth: usize, f: &mut FnMut(P<Expr>)) {
    if depth == 0 {
        f(make_x());
        return;
    }

    let mut g = |e| f(expr(e));

    for kind in 0 .. 17 {
        match kind {
            0 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Box(e))),
            1 => {
                // Note that for binary expressions, we explore each side separately.  The
                // parenthesization decisions for the LHS and RHS should be independent, and this
                // way produces `O(n)` results instead of `O(n^2)`.
                iter_exprs(depth - 1, &mut |e| g(ExprKind::InPlace(e, make_x())));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::InPlace(make_x(), e)));
            },
            2 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Call(e, vec![]))),
            3 => {
                let seg = PathSegment {
                    identifier: Ident::from_str("x"),
                    span: DUMMY_SP,
                    parameters: None,
                };

                iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall(
                            seg.clone(), vec![e, make_x()])));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall(
                            seg.clone(), vec![make_x(), e])));
            },
            4 => {
                let op = Spanned { span: DUMMY_SP, node: BinOpKind::Add };
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, e, make_x())));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, make_x(), e)));
            },
            5 => {
                let op = Spanned { span: DUMMY_SP, node: BinOpKind::Mul };
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, e, make_x())));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, make_x(), e)));
            },
            6 => {
                let op = Spanned { span: DUMMY_SP, node: BinOpKind::Shl };
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, e, make_x())));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, make_x(), e)));
            },
            7 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Unary(UnOp::Deref, e)));
            },
            8 => {
                let block = P(Block {
                    stmts: Vec::new(),
                    id: DUMMY_NODE_ID,
                    rules: BlockCheckMode::Default,
                    span: DUMMY_SP,
                });
                iter_exprs(depth - 1, &mut |e| g(ExprKind::If(e, block.clone(), None)));
            },
            9 => {
                let decl = P(FnDecl {
                    inputs: vec![],
                    output: FunctionRetTy::Default(DUMMY_SP),
                    variadic: false,
                });
                iter_exprs(depth - 1, &mut |e| g(
                        ExprKind::Closure(CaptureBy::Value, decl.clone(), e, DUMMY_SP)));
            },
            10 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Assign(e, make_x())));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Assign(make_x(), e)));
            },
            11 => {
                let ident = Spanned { span: DUMMY_SP, node: Ident::from_str("f") };
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Field(e, ident)));
            },
            12 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Range(
                            Some(e), Some(make_x()), RangeLimits::HalfOpen)));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Range(
                            Some(make_x()), Some(e), RangeLimits::HalfOpen)));
            },
            13 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::AddrOf(Mutability::Immutable, e)));
            },
            14 => {
                g(ExprKind::Ret(None));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Ret(Some(e))));
            },
            15 => {
                let seg = PathSegment {
                    identifier: Ident::from_str("S"),
                    span: DUMMY_SP,
                    parameters: None,
                };
                let path = Path {
                    span: DUMMY_SP,
                    segments: vec![seg],
                };
                g(ExprKind::Struct(path, vec![], Some(make_x())));
            },
            16 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Try(e)));
            },
            _ => panic!("bad counter value in iter_exprs"),
        }
    }
}

// Folders for manipulating the placement of `Paren` nodes.  See below for why this is needed.

/// Folder that removes all `ExprKind::Paren` nodes.
struct RemoveParens;

impl Folder for RemoveParens {
    fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
        let e = match e.node {
            ExprKind::Paren(ref inner) => inner.clone(),
            _ => e.clone(),
        };
        e.map(|e| fold::noop_fold_expr(e, self))
    }
}

/// Folder that inserts `ExprKind::Paren` nodes around every `Expr`.
struct AddParens;

impl Folder for AddParens {
    fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
        let e = e.map(|e| fold::noop_fold_expr(e, self));
        P(Expr {
            id: DUMMY_NODE_ID,
            node: ExprKind::Paren(e),
            span: DUMMY_SP,
            attrs: ThinVec::new(),
        })
    }
}

fn main() {
    let ps = ParseSess::new(FilePathMapping::empty());

    iter_exprs(2, &mut |e| {
        // If the pretty printer is correct, then `parse(print(e))` should be identical to `e`,
        // modulo placement of `Paren` nodes.
        let printed = pprust::expr_to_string(&e);
        println!("printed: {}", printed);

        let parsed = parse_expr(&ps, &printed);

        // We want to know if `parsed` is structurally identical to `e`, ignoring trivial
        // differences like placement of `Paren`s or the exact ranges of node spans.
        // Unfortunately, there is no easy way to make this comparison.  Instead, we add `Paren`s
        // everywhere we can, then pretty-print.  This should give an unambiguous representation of
        // each `Expr`, and it bypasses nearly all of the parenthesization logic, so we aren't
        // relying on the correctness of the very thing we're testing.
        let e1 = AddParens.fold_expr(RemoveParens.fold_expr(e));
        let text1 = pprust::expr_to_string(&e1);
        let e2 = AddParens.fold_expr(RemoveParens.fold_expr(parsed));
        let text2 = pprust::expr_to_string(&e2);
        assert!(text1 == text2,
                "exprs are not equal:\n  e =      {:?}\n  parsed = {:?}",
                text1, text2);
    });
}
<|endoftext|>


<commit_before>// xfail-win32 - random windows breakage

tag maybe_pointy {
    no_pointy;
    yes_pointy(@pointy);
}

type pointy = {
    mutable x : maybe_pointy
};

fn main() {
    let m = @{ mutable x : no_pointy };
    m.x = yes_pointy(m);
}
<commit_msg>xfail-win32 -> xfail-fast<commit_after>// xfail-fast - random windows breakage

tag maybe_pointy {
    no_pointy;
    yes_pointy(@pointy);
}

type pointy = {
    mutable x : maybe_pointy
};

fn main() {
    let m = @{ mutable x : no_pointy };
    m.x = yes_pointy(m);
}
<|endoftext|>


<commit_before>// -*- rust -*-

use std;
import std.deque;

fn test_simple() {
  let deque.t[int] d = deque.create[int]();
  check (d.size() == 0u);
  d.add_front(17);
  d.add_front(42);
  d.add_back(137);
  check (d.size() == 3u);
  d.add_back(137);
  check (d.size() == 4u);

  log d.peek_front();
  check (d.peek_front() == 42);

  log d.peek_back();
  check (d.peek_back() == 137);

  let int i = d.pop_front();
  log i;
  check (i == 42);

  i = d.pop_back();
  log i;
  check (i == 137);

  i = d.pop_back();
  log i;
  check (i == 137);

  i = d.pop_back();
  log i;
  check (i == 17);

  /* FIXME (issue #138):  Test d.get() once it no longer causes
   * segfault. */
}

fn test_boxes(@int a, @int b, @int c, @int d) {
  let deque.t[@int] deq = deque.create[@int]();
  check (deq.size() == 0u);
  deq.add_front(a);
  deq.add_front(b);
  deq.add_back(c);
  check (deq.size() == 3u);
  deq.add_back(d);
  check (deq.size() == 4u);

  check (deq.peek_front() == b);
  check (deq.peek_back() == d);

  check (deq.pop_front() == b);
  check (deq.pop_back() == d);
  check (deq.pop_back() == c);
  check (deq.pop_back() == a);

  /* FIXME (issue #138):  Test d.get() once it no longer causes
   * segfault. */
}

type eqfn[T] = fn(&T a, &T b) -> bool;

fn test_parameterized[T](eqfn[T] e, &T a, &T b, &T c, &T d) {
  let deque.t[T] deq = deque.create[T]();
  check (deq.size() == 0u);
  deq.add_front(a);
  deq.add_front(b);
  deq.add_back(c);
  check (deq.size() == 3u);
  deq.add_back(d);
  check (deq.size() == 4u);

  check (e(deq.peek_front(), b));
  check (e(deq.peek_back(), d));

  check (e(deq.pop_front(), b));
  check (e(deq.pop_back(), d));
  check (e(deq.pop_back(), c));
  check (e(deq.pop_back(), a));

  /* FIXME (issue #138):  Test d.get() once it no longer causes
   * segfault. */
}

type taggy = tag(one(int), two(int, int), three(int, int, int));

type taggypar[T] = tag(onepar(int),
                       twopar(int, int),
                       threepar(int, int, int));

type reccy = rec(int x, int y, taggy t);

fn main() {
  fn inteq(&int a, &int b) -> bool {
    ret a == b;
  }

  fn intboxeq(&@int a, &@int b) -> bool {
    ret a == b;
  }

  fn taggyeq(&taggy a, &taggy b) -> bool {
    alt (a) {
      case (one(a1)) {
        alt (b) {
          case (one(b1)) { ret a1 == b1; }
          case (_) { ret false; }
        }
      }
      case (two(a1, a2)) {
        alt (b) {
          case (two(b1, b2)) { ret (a1 == b1 && a2 == b2); }
          case (_) { ret false; }
        }
      }
      case (three(a1, a2, a3)) {
        alt (b) {
          case (three(b1, b2, b3)) { ret (a1 == b1 && a2 == b2 && a3 == b3); }
          case (_) { ret false; }
        }
      }
    }
  }

  fn taggypareq[T](&taggypar[T] a, &taggypar[T] b) -> bool {
    alt (a) {
      case (onepar[T](a1)) {
        alt (b) {
          case (onepar[T](b1)) { ret a1 == b1; }
          case (_) { ret false; }
        }
      }
      case (twopar[T](a1, a2)) {
        alt (b) {
          case (twopar[T](b1, b2)) { ret (a1 == b1 && a2 == b2); }
          case (_) { ret false; }
        }
      }
      case (threepar[T](a1, a2, a3)) {
        alt (b) {
          case (threepar[T](b1, b2, b3)) {
            ret (a1 == b1 && a2 == b2 && a3 == b3);
          }
          case (_) { ret false; }
        }
      }
    }
  }

  fn reccyeq(&reccy a, &reccy b) -> bool {
    ret (a.x == b.x && a.y == b.y && taggyeq(a.t, b.t));
  }

  log "test simple";
  test_simple();

  /*
   * FIXME: Causes "Invalid read of size 4" under valgrind.

  log "test boxes";
  test_boxes(@5, @72, @64, @175);

   */

  log "test parameterized: int";
  let eqfn[int] eq1 = bind inteq(_, _);
  test_parameterized[int](eq1, 5, 72, 64, 175);

  /*
   * FIXME: Appears to segfault after an upcall_grow_task

  log "test parameterized: @int";
  let eqfn[@int] eq2 = bind intboxeq(_, _);
  test_parameterized[@int](eq2, @5, @72, @64, @175);

   */

  log "test parameterized: taggy";
  let eqfn[taggy] eq3 = bind taggyeq(_, _);
  test_parameterized[taggy](eq3,
                            one(1), two(1, 2), three(1, 2, 3), two(17, 42));

  /*
   * FIXME: Segfault.

  log "test parameterized: taggypar[int]";
  let eqfn[taggypar[int]] eq4 = bind taggypareq[int](_, _);
  test_parameterized[taggypar[int]](eq4,
                                    onepar[int](1),
                                    twopar[int](1, 2),
                                    threepar[int](1, 2, 3),
                                    twopar[int](17, 42));

   */

  /*
   * FIXME: Segfault.

  log "test parameterized: reccy";
  let reccy reccy1 = rec(x=1, y=2, t=one(1));
  let reccy reccy2 = rec(x=345, y=2, t=two(1, 2));
  let reccy reccy3 = rec(x=1, y=777, t=three(1, 2, 3));
  let reccy reccy4 = rec(x=19, y=252, t=two(17, 42));
  let eqfn[reccy] eq5 = bind reccyeq(_, _);
  test_parameterized[reccy](eq5,
                            reccy1, reccy2, reccy3, reccy4);

   */

  log "done";
}
<commit_msg>Uncomment recently-no-longer-failing std.deque tests.  Add a few arbitrary-access checks.<commit_after>// -*- rust -*-

use std;
import std.deque;

fn test_simple() {
  let deque.t[int] d = deque.create[int]();
  check (d.size() == 0u);
  d.add_front(17);
  d.add_front(42);
  d.add_back(137);
  check (d.size() == 3u);
  d.add_back(137);
  check (d.size() == 4u);

  log d.peek_front();
  check (d.peek_front() == 42);

  log d.peek_back();
  check (d.peek_back() == 137);

  let int i = d.pop_front();
  log i;
  check (i == 42);

  i = d.pop_back();
  log i;
  check (i == 137);

  i = d.pop_back();
  log i;
  check (i == 137);

  i = d.pop_back();
  log i;
  check (i == 17);

  check (d.size() == 0u);
  d.add_back(3);
  check (d.size() == 1u);
  d.add_front(2);
  check (d.size() == 2u);
  d.add_back(4);
  check (d.size() == 3u);
  d.add_front(1);
  check (d.size() == 4u);

  log d.get(0);
  log d.get(1);
  log d.get(2);
  log d.get(3);

  check (d.get(0) == 1);
  check (d.get(1) == 2);
  check (d.get(2) == 3);
  check (d.get(3) == 4);
}

fn test_boxes(@int a, @int b, @int c, @int d) {
  let deque.t[@int] deq = deque.create[@int]();
  check (deq.size() == 0u);
  deq.add_front(a);
  deq.add_front(b);
  deq.add_back(c);
  check (deq.size() == 3u);
  deq.add_back(d);
  check (deq.size() == 4u);

  check (deq.peek_front() == b);
  check (deq.peek_back() == d);

  check (deq.pop_front() == b);
  check (deq.pop_back() == d);
  check (deq.pop_back() == c);
  check (deq.pop_back() == a);

  check (deq.size() == 0u);
  deq.add_back(c);
  check (deq.size() == 1u);
  deq.add_front(b);
  check (deq.size() == 2u);
  deq.add_back(d);
  check (deq.size() == 3u);
  deq.add_front(a);
  check (deq.size() == 4u);

  check (deq.get(0) == a);
  check (deq.get(1) == b);
  check (deq.get(2) == c);
  check (deq.get(3) == d);
}

type eqfn[T] = fn(T a, T b) -> bool;

fn test_parameterized[T](eqfn[T] e, T a, T b, T c, T d) {
  let deque.t[T] deq = deque.create[T]();
  check (deq.size() == 0u);
  deq.add_front(a);
  deq.add_front(b);
  deq.add_back(c);
  check (deq.size() == 3u);
  deq.add_back(d);
  check (deq.size() == 4u);

  check (e(deq.peek_front(), b));
  check (e(deq.peek_back(), d));

  check (e(deq.pop_front(), b));
  check (e(deq.pop_back(), d));
  check (e(deq.pop_back(), c));
  check (e(deq.pop_back(), a));

  check (deq.size() == 0u);
  deq.add_back(c);
  check (deq.size() == 1u);
  deq.add_front(b);
  check (deq.size() == 2u);
  deq.add_back(d);
  check (deq.size() == 3u);
  deq.add_front(a);
  check (deq.size() == 4u);

  check (e(deq.get(0), a));
  check (e(deq.get(1), b));
  check (e(deq.get(2), c));
  check (e(deq.get(3), d));
}

type taggy = tag(one(int), two(int, int), three(int, int, int));

type taggypar[T] = tag(onepar(int),
                       twopar(int, int),
                       threepar(int, int, int));

type reccy = rec(int x, int y, taggy t);

fn main() {
  fn inteq(int a, int b) -> bool {
    ret a == b;
  }

  fn intboxeq(@int a, @int b) -> bool {
    ret a == b;
  }

  fn taggyeq(taggy a, taggy b) -> bool {
    alt (a) {
      case (one(a1)) {
        alt (b) {
          case (one(b1)) { ret a1 == b1; }
          case (_) { ret false; }
        }
      }
      case (two(a1, a2)) {
        alt (b) {
          case (two(b1, b2)) { ret (a1 == b1 && a2 == b2); }
          case (_) { ret false; }
        }
      }
      case (three(a1, a2, a3)) {
        alt (b) {
          case (three(b1, b2, b3)) { ret (a1 == b1 && a2 == b2 && a3 == b3); }
          case (_) { ret false; }
        }
      }
    }
  }

  fn taggypareq[T](taggypar[T] a, taggypar[T] b) -> bool {
    alt (a) {
      case (onepar[T](a1)) {
        alt (b) {
          case (onepar[T](b1)) { ret a1 == b1; }
          case (_) { ret false; }
        }
      }
      case (twopar[T](a1, a2)) {
        alt (b) {
          case (twopar[T](b1, b2)) { ret (a1 == b1 && a2 == b2); }
          case (_) { ret false; }
        }
      }
      case (threepar[T](a1, a2, a3)) {
        alt (b) {
          case (threepar[T](b1, b2, b3)) {
            ret (a1 == b1 && a2 == b2 && a3 == b3);
          }
          case (_) { ret false; }
        }
      }
    }
  }

  fn reccyeq(reccy a, reccy b) -> bool {
    ret (a.x == b.x && a.y == b.y && taggyeq(a.t, b.t));
  }

  log "*** starting";

  log "*** test simple";
  test_simple();
  log "*** end test simple";

  /*
   * FIXME: Causes "Invalid read of size 4" under valgrind.

  log "*** test boxes";
  test_boxes(@5, @72, @64, @175);
  log "*** end test boxes";

   */

  log "test parameterized: int";
  let eqfn[int] eq1 = inteq;
  test_parameterized[int](eq1, 5, 72, 64, 175);

  /*
   * FIXME: Appears to segfault after an upcall_grow_task

  log "*** test parameterized: @int";
  let eqfn[@int] eq2 = intboxeq;
  test_parameterized[@int](eq2, @5, @72, @64, @175);
  log "*** end test parameterized @int";

  */

  log "test parameterized: taggy";
  let eqfn[taggy] eq3 = taggyeq;
  test_parameterized[taggy](eq3,
                            one(1), two(1, 2), three(1, 2, 3), two(17, 42));

  /*
   * FIXME: Segfault.  Also appears to be caused only after upcall_grow_task

  log "*** test parameterized: taggypar[int]";
  let eqfn[taggypar[int]] eq4 = taggypareq[int];
  test_parameterized[taggypar[int]](eq4,
                                    onepar[int](1),
                                    twopar[int](1, 2),
                                    threepar[int](1, 2, 3),
                                    twopar[int](17, 42));
  log "*** end test parameterized: taggypar[int]";

   */

  log "*** test parameterized: reccy";
  let reccy reccy1 = rec(x=1, y=2, t=one(1));
  let reccy reccy2 = rec(x=345, y=2, t=two(1, 2));
  let reccy reccy3 = rec(x=1, y=777, t=three(1, 2, 3));
  let reccy reccy4 = rec(x=19, y=252, t=two(17, 42));
  let eqfn[reccy] eq5 = reccyeq;
  test_parameterized[reccy](eq5,
                            reccy1, reccy2, reccy3, reccy4);
  log "*** end test parameterized: reccy";

  log "*** done";
}
<|endoftext|>


<commit_before>extern crate libc;

use std::io::fs;
use std::io::fs::PathExtensions;
use std::io::File;
use std::io::IoResult;
use std::path::Path;
use std::collections::HashMap;

use document::Document;
use util;

pub fn build(source: &Path, dest: &Path) -> IoResult<()>{
    // TODO make configurable
    let template_extensions = ["tpl", "md"];

    let layouts_path = source.join("_layouts");
    let mut layouts = HashMap::new();

    match fs::walk_dir(&layouts_path) {
        Ok(mut files) => for layout in files {
            if(layout.is_file()){
                let text = File::open(&layout).read_to_string().unwrap();
                layouts.insert(layout.filename_str().unwrap().to_string(), text);
            }
        },
        Err(_) => println!("Warning: No layout path found ({})\n", source.display())
    };

    // create posts
    let posts : Vec<Document> = match fs::walk_dir(source) {
        Ok(directories) => directories.filter_map(|p|
                if template_extensions.contains(&p.extension_str().unwrap_or(""))
                && p.dir_path() != layouts_path {
                    Some(parse_document(&p, source))
                }else{
                    None
                }
            ).collect(),
        Err(_) => panic!("Path {} doesn't exist\n", source.display())
    };

    for post in posts.iter() {
        try!(post.create_file(dest, &layouts));
    }

    // copy everything
    if source != dest {
        try!(util::copy_recursive_filter(source, dest, |p| -> bool {
            !p.filename_str().unwrap().starts_with(".")
            && !template_extensions.contains(&p.extension_str().unwrap_or(""))
            && p != dest
            && p != &layouts_path
        }));
    }

    Ok(())
}

fn parse_document(path: &Path, source: &Path) -> Document {
    let attributes   = extract_attributes(path);
    let content      = extract_content(path);
    let mut new_path = path.path_relative_from(source).unwrap();
    new_path.set_extension("html");

    Document::new(
        attributes,
        content,
        new_path
    )
}

fn parse_file(path: &Path) -> String {
    match File::open(path) {
        // TODO handle IOResult
        Ok(mut x) => x.read_to_string().unwrap(),
        Err(_) => panic!("File {} doesn't exist\n", path.display())
    }
}

fn extract_attributes(path: &Path) -> HashMap<String, String> {
    let mut attributes = HashMap::new();
    attributes.insert("name".to_string(), path.filestem_str().unwrap().to_string());

    let content = parse_file(path);

    if content.as_slice().contains("---") {
        let mut content_splits = content.as_slice().split_str("---");

        let attribute_string = content_splits.nth(0u).unwrap();

        for attribute_line in attribute_string.split_str("\n") {
            if !attribute_line.contains_char(':') {
                continue;
            }

            let mut attribute_split = attribute_line.split(':');

            // TODO: Refactor, find a better way for doing this
            // .nth() method is consuming the iterator and therefore the 0th index on the second method
            // is in real index 1
            let key   = attribute_split.nth(0u).unwrap().trim_chars(' ').to_string().clone();
            let value = attribute_split.nth(0u).unwrap().trim_chars(' ').to_string().clone();

            attributes.insert(key, value);
        }
    }

    return attributes;
}

fn extract_content(path: &Path) -> String {
    let content = parse_file(path);

    if content.as_slice().contains("---") {
        let mut content_splits = content.as_slice().split_str("---");

        return content_splits.nth(1u).unwrap().to_string();
    }

    return content;
}
<commit_msg>remove explicit use for Path - is loaded by default via prelude module (http://doc.rust-lang.org/std/prelude/)<commit_after>extern crate libc;

use std::io::fs;
use std::io::fs::PathExtensions;
use std::io::File;
use std::io::IoResult;
use std::collections::HashMap;

use document::Document;
use util;

pub fn build(source: &Path, dest: &Path) -> IoResult<()>{
    // TODO make configurable
    let template_extensions = ["tpl", "md"];

    let layouts_path = source.join("_layouts");
    let mut layouts = HashMap::new();

    match fs::walk_dir(&layouts_path) {
        Ok(mut files) => for layout in files {
            if(layout.is_file()){
                let text = File::open(&layout).read_to_string().unwrap();
                layouts.insert(layout.filename_str().unwrap().to_string(), text);
            }
        },
        Err(_) => println!("Warning: No layout path found ({})\n", source.display())
    };

    // create posts
    let posts : Vec<Document> = match fs::walk_dir(source) {
        Ok(directories) => directories.filter_map(|p|
                if template_extensions.contains(&p.extension_str().unwrap_or(""))
                && p.dir_path() != layouts_path {
                    Some(parse_document(&p, source))
                }else{
                    None
                }
            ).collect(),
        Err(_) => panic!("Path {} doesn't exist\n", source.display())
    };

    for post in posts.iter() {
        try!(post.create_file(dest, &layouts));
    }

    // copy everything
    if source != dest {
        try!(util::copy_recursive_filter(source, dest, |p| -> bool {
            !p.filename_str().unwrap().starts_with(".")
            && !template_extensions.contains(&p.extension_str().unwrap_or(""))
            && p != dest
            && p != &layouts_path
        }));
    }

    Ok(())
}

fn parse_document(path: &Path, source: &Path) -> Document {
    let attributes   = extract_attributes(path);
    let content      = extract_content(path);
    let mut new_path = path.path_relative_from(source).unwrap();
    new_path.set_extension("html");

    Document::new(
        attributes,
        content,
        new_path
    )
}

fn parse_file(path: &Path) -> String {
    match File::open(path) {
        // TODO handle IOResult
        Ok(mut x) => x.read_to_string().unwrap(),
        Err(_) => panic!("File {} doesn't exist\n", path.display())
    }
}

fn extract_attributes(path: &Path) -> HashMap<String, String> {
    let mut attributes = HashMap::new();
    attributes.insert("name".to_string(), path.filestem_str().unwrap().to_string());

    let content = parse_file(path);

    if content.as_slice().contains("---") {
        let mut content_splits = content.as_slice().split_str("---");

        let attribute_string = content_splits.nth(0u).unwrap();

        for attribute_line in attribute_string.split_str("\n") {
            if !attribute_line.contains_char(':') {
                continue;
            }

            let mut attribute_split = attribute_line.split(':');

            // TODO: Refactor, find a better way for doing this
            // .nth() method is consuming the iterator and therefore the 0th index on the second method
            // is in real index 1
            let key   = attribute_split.nth(0u).unwrap().trim_chars(' ').to_string().clone();
            let value = attribute_split.nth(0u).unwrap().trim_chars(' ').to_string().clone();

            attributes.insert(key, value);
        }
    }

    return attributes;
}

fn extract_content(path: &Path) -> String {
    let content = parse_file(path);

    if content.as_slice().contains("---") {
        let mut content_splits = content.as_slice().split_str("---");

        return content_splits.nth(1u).unwrap().to_string();
    }

    return content;
}
<|endoftext|>


<commit_before><commit_msg>Trim starting `/` from relative entry path<commit_after><|endoftext|>


<commit_before>use std::ascii::AsciiExt;
use std::borrow::ToOwned;
use std::env;
use std::fs;
use std::io::{self, Read, Write};
use std::ops::Deref;
use std::path::PathBuf;

use csv;
use csv::index::Indexed;
use rustc_serialize::{Decodable, Decoder};

use CliResult;
use select::{SelectColumns, Selection, NormalSelection};
use util;

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

/// Delimiter represents values that can be passed from the command line that
/// can be used as a field delimiter in CSV data.
///
/// Its purpose is to ensure that the Unicode character given decodes to a
/// valid ASCII character as required by the CSV parser.
impl Delimiter {
    pub fn as_byte(self) -> u8 {
        let Delimiter(b) = self;
        b
    }
}

impl Decodable for Delimiter {
    fn decode<D: Decoder>(d: &mut D) -> Result<Delimiter, D::Error> {
        let c = try!(d.read_str());
        match &*c {
            r"\t" => Ok(Delimiter(b'\t')),
            s => {
                if s.len() != 1 {
                    let msg = format!("Could not convert '{}' to a single \
                                       ASCII character.", s);
                    return Err(d.error(&*msg));
                }
                let c = s.chars().next().unwrap();
                if c.is_ascii() {
                    Ok(Delimiter(c as u8))
                } else {
                    let msg = format!("Could not convert '{}' \
                                       to ASCII delimiter.", c);
                    Err(d.error(&*msg))
                }
            }
        }
    }
}

pub struct Config {
    path: Option<PathBuf>, // None implies <stdin>
    idx_path: Option<PathBuf>,
    select_columns: Option<SelectColumns>,
    delimiter: u8,
    pub no_headers: bool,
    flexible: bool,
    crlf: bool,
}

impl Config {
    pub fn new(path: &Option<String>) -> Config {
        let (path, delim) = match *path {
            None => (None, b','),
            Some(ref s) if s.deref() == "-" => (None, b','),
            Some(ref s) => {
                let path = PathBuf::from(s);
                let delim =
                    if path.extension().map(|v| v == "tsv").unwrap_or(false) {
                        b'\t'
                    } else {
                        b','
                    };
                (Some(path), delim)
            }
        };
        Config {
            path: path,
            idx_path: None,
            select_columns: None,
            delimiter: delim,
            no_headers: false,
            flexible: false,
            crlf: false,
        }
    }

    pub fn delimiter(mut self, d: Option<Delimiter>) -> Config {
        if let Some(d) = d {
            self.delimiter = d.as_byte();
        }
        self
    }

    pub fn no_headers(mut self, mut yes: bool) -> Config {
        if env::var("XSV_TOGGLE_HEADERS").unwrap_or("0".to_owned()) == "1" {
            yes = !yes;
        }
        self.no_headers = yes;
        self
    }

    pub fn flexible(mut self, yes: bool) -> Config {
        self.flexible = yes;
        self
    }

    pub fn crlf(mut self, yes: bool) -> Config {
        self.crlf = yes;
        self
    }

    pub fn select(mut self, sel_cols: SelectColumns) -> Config {
        self.select_columns = Some(sel_cols);
        self
    }

    pub fn is_std(&self) -> bool {
        self.path.is_none()
    }

    pub fn selection(&self, first_record: &[csv::ByteString])
                    -> Result<Selection, String> {
        match self.select_columns {
            None => Err("Config has no 'SelectColums'. Did you call \
                         Config::select?".to_string()),
            Some(ref sel) => sel.selection(first_record, !self.no_headers),
        }
    }

    pub fn normal_selection(&self, first_record: &[csv::ByteString])
                    -> Result<NormalSelection, String> {
        self.selection(first_record).map(|sel| sel.normal())
    }

    pub fn write_headers<R: io::Read, W: io::Write>
                        (&self, r: &mut csv::Reader<R>, w: &mut csv::Writer<W>)
                        -> csv::Result<()> {
        if !self.no_headers {
            let r = try!(r.byte_headers());
            if !r.is_empty() {
                try!(w.write(r.into_iter()));
            }
        }
        Ok(())
    }

    pub fn writer(&self)
                 -> io::Result<csv::Writer<Box<io::Write+'static>>> {
        Ok(self.from_writer(try!(self.io_writer())))
    }

    pub fn reader(&self)
                 -> io::Result<csv::Reader<Box<io::Read+'static>>> {
        Ok(self.from_reader(try!(self.io_reader())))
    }

    pub fn reader_file(&self) -> io::Result<csv::Reader<fs::File>> {
        match self.path {
            None => Err(io::Error::new(
                io::ErrorKind::Other, "Cannot use <stdin> here", None,
            )),
            Some(ref p) => fs::File::open(p).map(|f| self.from_reader(f)),
        }
    }

    pub fn index_files(&self)
           -> io::Result<Option<(csv::Reader<fs::File>, fs::File)>> {
        let (csv_file, idx_file) = match (&self.path, &self.idx_path) {
            (&None, &None) => return Ok(None),
            (&None, &Some(ref p)) => return Err(io::Error::new(
                io::ErrorKind::Other,
                "Cannot use <stdin> with indexes",
                Some(format!("index file: {}", p.display()))
            )),
            (&Some(ref p), &None) => {
                // We generally don't want to report an error here, since we're
                // passively trying to find an index.
                let idx_file = match fs::File::open(&util::idx_path(p)) {
                    // TODO: Maybe we should report an error if the file exists
                    // but is not readable.
                    Err(_) => return Ok(None),
                    Ok(f) => f,
                };
                (try!(fs::File::open(p)), idx_file)
            }
            (&Some(ref p), &Some(ref ip)) => {
                (try!(fs::File::open(p)), try!(fs::File::open(ip)))
            }
        };
        // If the CSV data was last modified after the index file was last
        // modified, then return an error and demand the user regenerate the
        // index.
        let data_modified = try!(csv_file.metadata()).modified();
        let idx_modified = try!(idx_file.metadata()).modified();
        if data_modified > idx_modified {
            return Err(io::Error::new(
                io::ErrorKind::Other,
                "The CSV file was modified after the index file. \
                 Please re-create the index.",
                Some(format!("CSV file: {}, index file: {}",
                             csv_file.path().unwrap().to_string_lossy(),
                             idx_file.path().unwrap().to_string_lossy())),
            ));
        }
        let csv_rdr = self.from_reader(csv_file);
        Ok(Some((csv_rdr, idx_file)))
    }

    pub fn indexed(&self)
                  -> CliResult<Option<Indexed<fs::File, fs::File>>> {
        match try!(self.index_files()) {
            None => Ok(None),
            Some((r, i)) => Ok(Some(try!(Indexed::new(r, i)))),
        }
    }

    pub fn io_reader(&self) -> io::Result<Box<io::Read+'static>> {
        Ok(match self.path {
            None => Box::new(io::stdin()),
            Some(ref p) => Box::new(try!(fs::File::open(p))),
        })
    }

    pub fn from_reader<R: Read>(&self, rdr: R) -> csv::Reader<R> {
        csv::Reader::from_reader(rdr)
                    .flexible(self.flexible)
                    .delimiter(self.delimiter)
                    .has_headers(!self.no_headers)
    }

    pub fn io_writer(&self) -> io::Result<Box<io::Write+'static>> {
        Ok(match self.path {
            None => Box::new(io::stdout()),
            Some(ref p) => Box::new(try!(fs::File::create(p))),
        })
    }

    pub fn from_writer<W: io::Write>(&self, wtr: W) -> csv::Writer<W> {
        let term = if self.crlf { csv::RecordTerminator::CRLF }
                   else { csv::RecordTerminator::Any(b'\n') };
        csv::Writer::from_writer(wtr)
                    .flexible(self.flexible)
                    .delimiter(self.delimiter)
                    .record_terminator(term)
    }
}
<commit_msg>Simplify.<commit_after>use std::ascii::AsciiExt;
use std::borrow::ToOwned;
use std::env;
use std::fs;
use std::io::{self, Read, Write};
use std::ops::Deref;
use std::path::PathBuf;

use csv;
use csv::index::Indexed;
use rustc_serialize::{Decodable, Decoder};

use CliResult;
use select::{SelectColumns, Selection, NormalSelection};
use util;

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

/// Delimiter represents values that can be passed from the command line that
/// can be used as a field delimiter in CSV data.
///
/// Its purpose is to ensure that the Unicode character given decodes to a
/// valid ASCII character as required by the CSV parser.
impl Delimiter {
    pub fn as_byte(self) -> u8 {
        self.0
    }
}

impl Decodable for Delimiter {
    fn decode<D: Decoder>(d: &mut D) -> Result<Delimiter, D::Error> {
        let c = try!(d.read_str());
        match &*c {
            r"\t" => Ok(Delimiter(b'\t')),
            s => {
                if s.len() != 1 {
                    let msg = format!("Could not convert '{}' to a single \
                                       ASCII character.", s);
                    return Err(d.error(&*msg));
                }
                let c = s.chars().next().unwrap();
                if c.is_ascii() {
                    Ok(Delimiter(c as u8))
                } else {
                    let msg = format!("Could not convert '{}' \
                                       to ASCII delimiter.", c);
                    Err(d.error(&*msg))
                }
            }
        }
    }
}

pub struct Config {
    path: Option<PathBuf>, // None implies <stdin>
    idx_path: Option<PathBuf>,
    select_columns: Option<SelectColumns>,
    delimiter: u8,
    pub no_headers: bool,
    flexible: bool,
    crlf: bool,
}

impl Config {
    pub fn new(path: &Option<String>) -> Config {
        let (path, delim) = match *path {
            None => (None, b','),
            Some(ref s) if s.deref() == "-" => (None, b','),
            Some(ref s) => {
                let path = PathBuf::from(s);
                let delim =
                    if path.extension().map(|v| v == "tsv").unwrap_or(false) {
                        b'\t'
                    } else {
                        b','
                    };
                (Some(path), delim)
            }
        };
        Config {
            path: path,
            idx_path: None,
            select_columns: None,
            delimiter: delim,
            no_headers: false,
            flexible: false,
            crlf: false,
        }
    }

    pub fn delimiter(mut self, d: Option<Delimiter>) -> Config {
        if let Some(d) = d {
            self.delimiter = d.as_byte();
        }
        self
    }

    pub fn no_headers(mut self, mut yes: bool) -> Config {
        if env::var("XSV_TOGGLE_HEADERS").unwrap_or("0".to_owned()) == "1" {
            yes = !yes;
        }
        self.no_headers = yes;
        self
    }

    pub fn flexible(mut self, yes: bool) -> Config {
        self.flexible = yes;
        self
    }

    pub fn crlf(mut self, yes: bool) -> Config {
        self.crlf = yes;
        self
    }

    pub fn select(mut self, sel_cols: SelectColumns) -> Config {
        self.select_columns = Some(sel_cols);
        self
    }

    pub fn is_std(&self) -> bool {
        self.path.is_none()
    }

    pub fn selection(&self, first_record: &[csv::ByteString])
                    -> Result<Selection, String> {
        match self.select_columns {
            None => Err("Config has no 'SelectColums'. Did you call \
                         Config::select?".to_string()),
            Some(ref sel) => sel.selection(first_record, !self.no_headers),
        }
    }

    pub fn normal_selection(&self, first_record: &[csv::ByteString])
                    -> Result<NormalSelection, String> {
        self.selection(first_record).map(|sel| sel.normal())
    }

    pub fn write_headers<R: io::Read, W: io::Write>
                        (&self, r: &mut csv::Reader<R>, w: &mut csv::Writer<W>)
                        -> csv::Result<()> {
        if !self.no_headers {
            let r = try!(r.byte_headers());
            if !r.is_empty() {
                try!(w.write(r.into_iter()));
            }
        }
        Ok(())
    }

    pub fn writer(&self)
                 -> io::Result<csv::Writer<Box<io::Write+'static>>> {
        Ok(self.from_writer(try!(self.io_writer())))
    }

    pub fn reader(&self)
                 -> io::Result<csv::Reader<Box<io::Read+'static>>> {
        Ok(self.from_reader(try!(self.io_reader())))
    }

    pub fn reader_file(&self) -> io::Result<csv::Reader<fs::File>> {
        match self.path {
            None => Err(io::Error::new(
                io::ErrorKind::Other, "Cannot use <stdin> here", None,
            )),
            Some(ref p) => fs::File::open(p).map(|f| self.from_reader(f)),
        }
    }

    pub fn index_files(&self)
           -> io::Result<Option<(csv::Reader<fs::File>, fs::File)>> {
        let (csv_file, idx_file) = match (&self.path, &self.idx_path) {
            (&None, &None) => return Ok(None),
            (&None, &Some(ref p)) => return Err(io::Error::new(
                io::ErrorKind::Other,
                "Cannot use <stdin> with indexes",
                Some(format!("index file: {}", p.display()))
            )),
            (&Some(ref p), &None) => {
                // We generally don't want to report an error here, since we're
                // passively trying to find an index.
                let idx_file = match fs::File::open(&util::idx_path(p)) {
                    // TODO: Maybe we should report an error if the file exists
                    // but is not readable.
                    Err(_) => return Ok(None),
                    Ok(f) => f,
                };
                (try!(fs::File::open(p)), idx_file)
            }
            (&Some(ref p), &Some(ref ip)) => {
                (try!(fs::File::open(p)), try!(fs::File::open(ip)))
            }
        };
        // If the CSV data was last modified after the index file was last
        // modified, then return an error and demand the user regenerate the
        // index.
        let data_modified = try!(csv_file.metadata()).modified();
        let idx_modified = try!(idx_file.metadata()).modified();
        if data_modified > idx_modified {
            return Err(io::Error::new(
                io::ErrorKind::Other,
                "The CSV file was modified after the index file. \
                 Please re-create the index.",
                Some(format!("CSV file: {}, index file: {}",
                             csv_file.path().unwrap().to_string_lossy(),
                             idx_file.path().unwrap().to_string_lossy())),
            ));
        }
        let csv_rdr = self.from_reader(csv_file);
        Ok(Some((csv_rdr, idx_file)))
    }

    pub fn indexed(&self)
                  -> CliResult<Option<Indexed<fs::File, fs::File>>> {
        match try!(self.index_files()) {
            None => Ok(None),
            Some((r, i)) => Ok(Some(try!(Indexed::new(r, i)))),
        }
    }

    pub fn io_reader(&self) -> io::Result<Box<io::Read+'static>> {
        Ok(match self.path {
            None => Box::new(io::stdin()),
            Some(ref p) => Box::new(try!(fs::File::open(p))),
        })
    }

    pub fn from_reader<R: Read>(&self, rdr: R) -> csv::Reader<R> {
        csv::Reader::from_reader(rdr)
                    .flexible(self.flexible)
                    .delimiter(self.delimiter)
                    .has_headers(!self.no_headers)
    }

    pub fn io_writer(&self) -> io::Result<Box<io::Write+'static>> {
        Ok(match self.path {
            None => Box::new(io::stdout()),
            Some(ref p) => Box::new(try!(fs::File::create(p))),
        })
    }

    pub fn from_writer<W: io::Write>(&self, wtr: W) -> csv::Writer<W> {
        let term = if self.crlf { csv::RecordTerminator::CRLF }
                   else { csv::RecordTerminator::Any(b'\n') };
        csv::Writer::from_writer(wtr)
                    .flexible(self.flexible)
                    .delimiter(self.delimiter)
                    .record_terminator(term)
    }
}
<|endoftext|>


<commit_before><commit_msg>add module file<commit_after>use std::rc::Rc;
use std::path::PathBuf;
use std::ffi::OsString;
use std::vec;

use syntex_syntax::{ast, ptr};

#[derive(Default, Debug, Clone)]
pub struct Module {
    pub list: Vec<ptr::P<ast::Item>>,
    pub path: Vec<OsString>,
}

impl From<(Vec<ptr::P<ast::Item>>, PathBuf)> for Module {
    fn from((list, mut path): (Vec<ptr::P<ast::Item>>, PathBuf)) -> Module {
        path.set_extension("");
        Module {
            list: list,
            path: path.components()
                      .skip(1)
                      .map(|comp| comp.as_os_str().to_os_string())
                      .collect::<Vec<OsString>>(),
        }
    }
}

impl IntoIterator for Module {
    type Item = (ptr::P<ast::Item>, Rc<Vec<OsString>>);
    type IntoIter = vec::IntoIter<(ptr::P<ast::Item>, Rc<Vec<OsString>>)>;

    fn into_iter(self) -> Self::IntoIter {
        let ref rc: Rc<Vec<OsString>> = Rc::new(self.path);
        self.list.into_iter()
                 .map(|item| (item, Rc::clone(rc)))
                 .collect::<Vec<(ptr::P<ast::Item>, Rc<Vec<OsString>>)>>()
                 .into_iter()
    }
}
<|endoftext|>


<commit_before><commit_msg>Add test<commit_after>// Copyright 2015 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.

// compile-flags: -Z unstable-options --unpretty=mir

fn main() {
    let x: () = 0; //~ ERROR: mismatched types
}
<|endoftext|>


<commit_before><commit_msg>Add duplicate test<commit_after>// Copyright 2016 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.

#![crate_name = "foo"]

mod foo {
    pub use bar::*;
    pub mod bar {
        pub trait Foo {
            fn foo();
        }
    }
}

// @count foo/index.html '//*[@class="trait"]' 1
pub use foo::bar::*;
pub use foo::*;
<|endoftext|>


<commit_before><commit_msg>Added Mortgage Calculator.<commit_after>
fn calculate_mortgage(amount :u64, interest :f64, years :u64) -> f64{
    let months = std::f64::ceil(years as f64 * 12f64);

    let r = interest / 12f64;
    let a = amount as f64 * (r / 100f64 * std::f64::pow(1f64+r/100f64, months as f64)) / (std::f64::pow(1f64+r/100f64, months as f64) - 1f64);
    a
}

fn main() {
    println!("Monthly Payment: {}", calculate_mortgage(1000, 3.4f64, 2));
}<|endoftext|>


<commit_before>// Copyright 2012-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.

//! Support for parsing unsupported, old syntaxes, for the purpose of reporting errors. Parsing of
//! these syntaxes is tested by compile-test/obsolete-syntax.rs.
//!
//! Obsolete syntax that becomes too hard to parse can be removed.

use ast::{Expr, ExprTup};
use codemap::Span;
use parse::parser;
use parse::token;
use ptr::P;

/// The specific types of unsupported syntax
#[derive(Copy, PartialEq, Eq, Hash)]
pub enum ObsoleteSyntax {
    Sized,
    OwnedType,
    OwnedExpr,
    OwnedPattern,
    OwnedVector,
    OwnedSelf,
    ImportRenaming,
    SubsliceMatch,
    ExternCrateRenaming,
    ProcType,
    ProcExpr,
}

pub trait ParserObsoleteMethods {
    /// Reports an obsolete syntax non-fatal error.
    fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax);
    /// Reports an obsolete syntax non-fatal error, and returns
    /// a placeholder expression
    fn obsolete_expr(&mut self, sp: Span, kind: ObsoleteSyntax) -> P<Expr>;
    fn report(&mut self,
              sp: Span,
              kind: ObsoleteSyntax,
              kind_str: &str,
              desc: &str);
    fn is_obsolete_ident(&mut self, ident: &str) -> bool;
    fn eat_obsolete_ident(&mut self, ident: &str) -> bool;
}

impl<'a> ParserObsoleteMethods for parser::Parser<'a> {
    /// Reports an obsolete syntax non-fatal error.
    fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) {
        let (kind_str, desc) = match kind {
            ObsoleteSyntax::ProcType => (
                "the `proc` type",
                "use unboxed closures instead",
            ),
            ObsoleteSyntax::ProcExpr => (
                "`proc` expression",
                "use a `move ||` expression instead",
            ),
            ObsoleteSyntax::OwnedType => (
                "`~` notation for owned pointers",
                "use `Box<T>` in `std::owned` instead"
            ),
            ObsoleteSyntax::OwnedExpr => (
                "`~` notation for owned pointer allocation",
                "use the `box` operator instead of `~`"
            ),
            ObsoleteSyntax::OwnedPattern => (
                "`~` notation for owned pointer patterns",
                "use the `box` operator instead of `~`"
            ),
            ObsoleteSyntax::OwnedVector => (
                "`~[T]` is no longer a type",
                "use the `Vec` type instead"
            ),
            ObsoleteSyntax::OwnedSelf => (
                "`~self` is no longer supported",
                "write `self: Box<Self>` instead"
            ),
            ObsoleteSyntax::ImportRenaming => (
                "`use foo = bar` syntax",
                "write `use bar as foo` instead"
            ),
            ObsoleteSyntax::SubsliceMatch => (
                "subslice match syntax",
                "instead of `..xs`, write `xs..` in a pattern"
            ),
            ObsoleteSyntax::ExternCrateRenaming => (
                "`extern crate foo = bar` syntax",
                "write `extern crate bar as foo` instead"
            ),
            ObsoleteSyntax::Sized => (
                "`T: ?Sized` syntax for removing the `Sized` bound",
                "write `T: ?Sized` instead"
            ),
        };

        self.report(sp, kind, kind_str, desc);
    }

    /// Reports an obsolete syntax non-fatal error, and returns
    /// a placeholder expression
    fn obsolete_expr(&mut self, sp: Span, kind: ObsoleteSyntax) -> P<Expr> {
        self.obsolete(sp, kind);
        self.mk_expr(sp.lo, sp.hi, ExprTup(vec![]))
    }

    fn report(&mut self,
              sp: Span,
              kind: ObsoleteSyntax,
              kind_str: &str,
              desc: &str) {
        self.span_err(sp,
                      format!("obsolete syntax: {}", kind_str)[]);

        if !self.obsolete_set.contains(&kind) {
            self.sess
                .span_diagnostic
                .handler()
                .note(format!("{}", desc)[]);
            self.obsolete_set.insert(kind);
        }
    }

    fn is_obsolete_ident(&mut self, ident: &str) -> bool {
        match self.token {
            token::Ident(sid, _) => {
                token::get_ident(sid) == ident
            }
            _ => false
        }
    }

    fn eat_obsolete_ident(&mut self, ident: &str) -> bool {
        if self.is_obsolete_ident(ident) {
            self.bump();
            true
        } else {
            false
        }
    }
}
<commit_msg>Fix the obsolete message<commit_after>// Copyright 2012-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.

//! Support for parsing unsupported, old syntaxes, for the purpose of reporting errors. Parsing of
//! these syntaxes is tested by compile-test/obsolete-syntax.rs.
//!
//! Obsolete syntax that becomes too hard to parse can be removed.

use ast::{Expr, ExprTup};
use codemap::Span;
use parse::parser;
use parse::token;
use ptr::P;

/// The specific types of unsupported syntax
#[derive(Copy, PartialEq, Eq, Hash)]
pub enum ObsoleteSyntax {
    Sized,
    OwnedType,
    OwnedExpr,
    OwnedPattern,
    OwnedVector,
    OwnedSelf,
    ImportRenaming,
    SubsliceMatch,
    ExternCrateRenaming,
    ProcType,
    ProcExpr,
}

pub trait ParserObsoleteMethods {
    /// Reports an obsolete syntax non-fatal error.
    fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax);
    /// Reports an obsolete syntax non-fatal error, and returns
    /// a placeholder expression
    fn obsolete_expr(&mut self, sp: Span, kind: ObsoleteSyntax) -> P<Expr>;
    fn report(&mut self,
              sp: Span,
              kind: ObsoleteSyntax,
              kind_str: &str,
              desc: &str);
    fn is_obsolete_ident(&mut self, ident: &str) -> bool;
    fn eat_obsolete_ident(&mut self, ident: &str) -> bool;
}

impl<'a> ParserObsoleteMethods for parser::Parser<'a> {
    /// Reports an obsolete syntax non-fatal error.
    fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) {
        let (kind_str, desc) = match kind {
            ObsoleteSyntax::ProcType => (
                "the `proc` type",
                "use unboxed closures instead",
            ),
            ObsoleteSyntax::ProcExpr => (
                "`proc` expression",
                "use a `move ||` expression instead",
            ),
            ObsoleteSyntax::OwnedType => (
                "`~` notation for owned pointers",
                "use `Box<T>` in `std::owned` instead"
            ),
            ObsoleteSyntax::OwnedExpr => (
                "`~` notation for owned pointer allocation",
                "use the `box` operator instead of `~`"
            ),
            ObsoleteSyntax::OwnedPattern => (
                "`~` notation for owned pointer patterns",
                "use the `box` operator instead of `~`"
            ),
            ObsoleteSyntax::OwnedVector => (
                "`~[T]` is no longer a type",
                "use the `Vec` type instead"
            ),
            ObsoleteSyntax::OwnedSelf => (
                "`~self` is no longer supported",
                "write `self: Box<Self>` instead"
            ),
            ObsoleteSyntax::ImportRenaming => (
                "`use foo = bar` syntax",
                "write `use bar as foo` instead"
            ),
            ObsoleteSyntax::SubsliceMatch => (
                "subslice match syntax",
                "instead of `..xs`, write `xs..` in a pattern"
            ),
            ObsoleteSyntax::ExternCrateRenaming => (
                "`extern crate foo = bar` syntax",
                "write `extern crate bar as foo` instead"
            ),
            ObsoleteSyntax::Sized => (
                "`Sized? T` syntax for removing the `Sized` bound",
                "write `T: ?Sized` instead"
            ),
        };

        self.report(sp, kind, kind_str, desc);
    }

    /// Reports an obsolete syntax non-fatal error, and returns
    /// a placeholder expression
    fn obsolete_expr(&mut self, sp: Span, kind: ObsoleteSyntax) -> P<Expr> {
        self.obsolete(sp, kind);
        self.mk_expr(sp.lo, sp.hi, ExprTup(vec![]))
    }

    fn report(&mut self,
              sp: Span,
              kind: ObsoleteSyntax,
              kind_str: &str,
              desc: &str) {
        self.span_err(sp,
                      format!("obsolete syntax: {}", kind_str)[]);

        if !self.obsolete_set.contains(&kind) {
            self.sess
                .span_diagnostic
                .handler()
                .note(format!("{}", desc)[]);
            self.obsolete_set.insert(kind);
        }
    }

    fn is_obsolete_ident(&mut self, ident: &str) -> bool {
        match self.token {
            token::Ident(sid, _) => {
                token::get_ident(sid) == ident
            }
            _ => false
        }
    }

    fn eat_obsolete_ident(&mut self, ident: &str) -> bool {
        if self.is_obsolete_ident(ident) {
            self.bump();
            true
        } else {
            false
        }
    }
}
<|endoftext|>


<commit_before>#![feature(std_misc)]

use std::sync::mpsc::{Sender, Receiver};
use std::sync::mpsc;
use std::thread::Thread;

static NTHREADS: usize = 3;

fn main() {
    // Channels have two endpoints: the `Sender<T>` and the `Receiver<T>`,
    // where `T` is the type of the message to be transfer
    // (type annotation is superfluous)
    let (tx, rx): (Sender<usize>, Receiver<usize>) = mpsc::channel();

    for id in 0..NTHREADS {
        // The sender endpoint can be copied
        let thread_tx = tx.clone();

        // Each thread will send its id via the channel
        Thread::spawn(move || {
            // The thread takes ownership over `thread_tx`
            // Each thread queues a message in the channel
            thread_tx.send(id).unwrap();

            // Sending is a non-blocking operation, the thread will continue
            // immediately after sending its message
            println!("thread {} finished", id);
        });
    }

    // Here, all the messages are collected
    let mut ids = Vec::with_capacity(NTHREADS);
    for _ in 0..NTHREADS {
        // The `recv` method picks a message from the channel
        // `recv` will block the current thread if there no messages available
        ids.push(rx.recv());
    }

    // Show the order in which the messages were sent
    println!("{:?}", ids);
}
<commit_msg>channels: fix typo in code comment.<commit_after>#![feature(std_misc)]

use std::sync::mpsc::{Sender, Receiver};
use std::sync::mpsc;
use std::thread::Thread;

static NTHREADS: usize = 3;

fn main() {
    // Channels have two endpoints: the `Sender<T>` and the `Receiver<T>`,
    // where `T` is the type of the message to be transferred
    // (type annotation is superfluous)
    let (tx, rx): (Sender<usize>, Receiver<usize>) = mpsc::channel();

    for id in 0..NTHREADS {
        // The sender endpoint can be copied
        let thread_tx = tx.clone();

        // Each thread will send its id via the channel
        Thread::spawn(move || {
            // The thread takes ownership over `thread_tx`
            // Each thread queues a message in the channel
            thread_tx.send(id).unwrap();

            // Sending is a non-blocking operation, the thread will continue
            // immediately after sending its message
            println!("thread {} finished", id);
        });
    }

    // Here, all the messages are collected
    let mut ids = Vec::with_capacity(NTHREADS);
    for _ in 0..NTHREADS {
        // The `recv` method picks a message from the channel
        // `recv` will block the current thread if there no messages available
        ids.push(rx.recv());
    }

    // Show the order in which the messages were sent
    println!("{:?}", ids);
}
<|endoftext|>


<commit_before>extern crate odbc;
use odbc::*;

#[test]
fn list_tables() {

    let mut env = Environment::new().unwrap();
    env.set_odbc_version_3().unwrap();
    let mut ds = DataSource::with_parent(&mut env).unwrap();
    ds.connect("PostgreSQL", "postgres", "").unwrap();
    // scope is required (for now) to close statement before disconnecting
    {
        let mut statement = Statement::with_parent(&mut ds).unwrap();
        statement.tables().unwrap();
        assert_eq!(statement.num_result_cols().unwrap(), 5);
    }
    ds.disconnect().unwrap();
}

#[test]
fn test_connection() {

    let mut environment = Environment::new().expect("Environment can be created");
    environment.set_odbc_version_3().unwrap();
    let mut conn = DataSource::with_parent(&mut environment).unwrap();
    conn.connect("PostgreSQL", "postgres", "").unwrap();

    assert!(!conn.read_only().unwrap());
    conn.disconnect().unwrap();
}

#[test]
fn list_drivers() {
    let mut environment = Environment::new().unwrap();
    environment.set_odbc_version_3().unwrap();
    let drivers = environment.drivers()
        .expect("Drivers can be iterated over");
    println!("{:?}", drivers);

    let expected = ["PostgreSQL ANSI", "PostgreSQL Unicode", "SQLite", "SQLite3"];
    assert!(drivers.iter().map(|d| &d.description).eq(expected.iter()));
}

#[test]
fn list_data_sources() {
    let mut environment = Environment::new().unwrap();
    environment.set_odbc_version_3().unwrap();
    let sources = environment.data_sources()
        .expect("Data sources can be iterated over");
    println!("{:?}", sources);

    let expected = [DataSourceInfo {
                        server_name: "PostgreSQL".to_owned(),
                        description: "PostgreSQL Unicode".to_owned(),
                    }];
    assert!(sources.iter().eq(expected.iter()));
}

#[test]
fn list_user_data_sources() {
    let mut environment = Environment::new().unwrap();
    environment.set_odbc_version_3().unwrap();
    let sources = environment.user_data_sources()
        .expect("Data sources can be iterated over");
    println!("{:?}", sources);

    let expected = [DataSourceInfo {
                        server_name: "PostgreSQL".to_owned(),
                        description: "PostgreSQL Unicode".to_owned(),
                    }];
    assert!(sources.iter().eq(expected.iter()));
}

#[test]
fn list_system_data_sources() {
    let mut environment = Environment::new().unwrap();
    environment.set_odbc_version_3().unwrap();
    let sources = environment.system_data_sources()
        .expect("Data sources can be iterated over");
    println!("{:?}", sources);

    let expected: [DataSourceInfo; 0] = [];
    assert!(sources.iter().eq(expected.iter()));
}

<commit_msg>added two tests for connection strings<commit_after>extern crate odbc;
use odbc::*;

#[test]
fn list_tables() {

    let mut env = Environment::new().unwrap();
    env.set_odbc_version_3().unwrap();
    let mut ds = DataSource::with_parent(&mut env).unwrap();
    ds.connect("PostgreSQL", "postgres", "").unwrap();
    // scope is required (for now) to close statement before disconnecting
    {
        let mut statement = Statement::with_parent(&mut ds).unwrap();
        statement.tables().unwrap();
        assert_eq!(statement.num_result_cols().unwrap(), 5);
    }
    ds.disconnect().unwrap();
}

#[test]
fn test_connection() {

    let mut environment = Environment::new().expect("Environment can be created");
    environment.set_odbc_version_3().unwrap();
    let mut conn = DataSource::with_parent(&mut environment).unwrap();
    conn.connect("PostgreSQL", "postgres", "").unwrap();

    assert!(!conn.read_only().unwrap());
    conn.disconnect().unwrap();
}

#[test]
fn test_invalid_connection_string() {

    let expected = if cfg!(target_os = "windows") {
        "State: IM002, Native error: 0, Message: [Microsoft][ODBC Driver Manager] Data source \
            name not found and no default driver specified"
    } else {
        "State: IM002, Native error: 0, Message: [unixODBC][Driver Manager]Data source name not \
            found, and no default driver specified"
    };

    let mut environment = Environment::new().unwrap();
    environment.set_odbc_version_3().unwrap();
    let mut conn = DataSource::with_parent(&environment).unwrap();
    let result = conn.connect_with_connection_string("bla");
    let message = format!("{}", result.err().unwrap());
    assert_eq!(expected, message);
}

#[test]
fn test_connection_string() {

    let mut environment = Environment::new().unwrap();
    environment.set_odbc_version_3().unwrap();
    let mut conn = DataSource::with_parent(&environment).unwrap();
    conn.connect_with_connection_string("dsn=PostgreSQL;Uid=postgres;Pwd=;")
        .unwrap();
    conn.disconnect().unwrap();
}

#[test]
fn list_drivers() {
    let mut environment = Environment::new().unwrap();
    environment.set_odbc_version_3().unwrap();
    let drivers = environment.drivers()
        .expect("Drivers can be iterated over");
    println!("{:?}", drivers);

    let expected = ["PostgreSQL ANSI", "PostgreSQL Unicode", "SQLite", "SQLite3"];
    assert!(drivers.iter().map(|d| &d.description).eq(expected.iter()));
}

#[test]
fn list_data_sources() {
    let mut environment = Environment::new().unwrap();
    environment.set_odbc_version_3().unwrap();
    let sources = environment.data_sources()
        .expect("Data sources can be iterated over");
    println!("{:?}", sources);

    let expected = [DataSourceInfo {
                        server_name: "PostgreSQL".to_owned(),
                        description: "PostgreSQL Unicode".to_owned(),
                    }];
    assert!(sources.iter().eq(expected.iter()));
}

#[test]
fn list_user_data_sources() {
    let mut environment = Environment::new().unwrap();
    environment.set_odbc_version_3().unwrap();
    let sources = environment.user_data_sources()
        .expect("Data sources can be iterated over");
    println!("{:?}", sources);

    let expected = [DataSourceInfo {
                        server_name: "PostgreSQL".to_owned(),
                        description: "PostgreSQL Unicode".to_owned(),
                    }];
    assert!(sources.iter().eq(expected.iter()));
}

#[test]
fn list_system_data_sources() {
    let mut environment = Environment::new().unwrap();
    environment.set_odbc_version_3().unwrap();
    let sources = environment.system_data_sources()
        .expect("Data sources can be iterated over");
    println!("{:?}", sources);

    let expected: [DataSourceInfo; 0] = [];
    assert!(sources.iter().eq(expected.iter()));
}

<|endoftext|>