<commit_before>#[doc = "Operations and constants for `float`"];

/*
Module: float
*/

// FIXME find out why these have to be exported explicitly

export to_str_common, to_str_exact, to_str, from_str;
export add, sub, mul, div, rem, lt, le, gt, eq, eq, ne;
export is_positive, is_negative, is_nonpositive, is_nonnegative;
export is_zero, is_infinite, is_finite;
export NaN, is_NaN, infinity, neg_infinity;
export consts;
export logarithm;
export acos, asin, atan, atan2, cbrt, ceil, copysign, cos, cosh, floor;
export erf, erfc, exp, expm1, exp2, abs, abs_sub;
export mul_add, fmax, fmin, nextafter, frexp, hypot, ldexp;
export lgamma, ln, log_radix, ln1p, log10, log2, ilog_radix;
export modf, pow, round, sin, sinh, sqrt, tan, tanh, tgamma, trunc;
export signbit;

// export when m_float == c_double

export j0, j1, jn, y0, y1, yn;

// PORT this must match in width according to architecture

import m_float = f64;
import f64::*;

type t = float;

/**
 * Section: String Conversions
 */

/*
Function: to_str_common

Converts a float to a string

Parameters:

num - The float value
digits - The number of significant digits
exact - Whether to enforce the exact number of significant digits
*/
fn to_str_common(num: float, digits: uint, exact: bool) -> str {
    if is_NaN(num) { ret "NaN"; }
    let (num, accum) = if num < 0.0 { (-num, "-") } else { (num, "") };
    let trunc = num as uint;
    let frac = num - (trunc as float);
    accum += uint::str(trunc);
    if (frac < epsilon && !exact) || digits == 0u { ret accum; }
    accum += ".";
    let i = digits;
    let epsilon = 1. / pow_uint_to_uint_as_float(10u, i);
    while i > 0u && (frac >= epsilon || exact) {
        frac *= 10.0;
        epsilon *= 10.0;
        let digit = frac as uint;
        accum += uint::str(digit);
        frac -= digit as float;
        i -= 1u;
    }
    ret accum;

}

/*
Function: to_str

Converts a float to a string with exactly the number of provided significant
digits

Parameters:

num - The float value
digits - The number of significant digits
*/
fn to_str_exact(num: float, digits: uint) -> str {
    to_str_common(num, digits, true)
}

#[test]
fn test_to_str_exact_do_decimal() {
    let s = to_str_exact(5.0, 4u);
    assert s == "5.0000";
}

/*
Function: to_str

Converts a float to a string with a maximum number of significant digits

Parameters:

num - The float value
digits - The number of significant digits
*/
fn to_str(num: float, digits: uint) -> str {
    to_str_common(num, digits, false)
}

/*
Function: from_str

Convert a string to a float

This function accepts strings such as
* "3.14"
* "+3.14", equivalent to "3.14"
* "-3.14"
* "2.5E10", or equivalently, "2.5e10"
* "2.5E-10"
* "", or, equivalently, "." (understood as 0)
* "5."
* ".5", or, equivalently,  "0.5"

Leading and trailing whitespace are ignored.

Parameters:

num - A string

Returns:

none if the string did not represent a valid number.
Otherwise, some(n) where n is the floating-point
number represented by [num].
*/
fn from_str(num: str) -> option<float> {
   let pos = 0u;                  //Current byte position in the string.
                                  //Used to walk the string in O(n).
   let len = str::len(num);  //Length of the string, in bytes.

   if len == 0u { ret none; }
   let total = 0f;                //Accumulated result
   let c     = 'z';               //Latest char.

   //The string must start with one of the following characters.
   alt str::char_at(num, 0u) {
      '-' | '+' | '0' to '9' | '.' {}
      _ { ret none; }
   }

   //Determine if first char is '-'/'+'. Set [pos] and [neg] accordingly.
   let neg = false;               //Sign of the result
   alt str::char_at(num, 0u) {
      '-' {
          neg = true;
          pos = 1u;
      }
      '+' {
          pos = 1u;
      }
      _ {}
   }

   //Examine the following chars until '.', 'e', 'E'
   while(pos < len) {
       let char_range = str::char_range_at(num, pos);
       c   = char_range.ch;
       pos = char_range.next;
       alt c {
         '0' to '9' {
           total = total * 10f;
           total += ((c as int) - ('0' as int)) as float;
         }
         '.' | 'e' | 'E' {
           break;
         }
         _ {
           ret none;
         }
       }
   }

   if c == '.' {//Examine decimal part
      let decimal = 1f;
      while(pos < len) {
         let char_range = str::char_range_at(num, pos);
         c = char_range.ch;
         pos = char_range.next;
         alt c {
            '0' | '1' | '2' | '3' | '4' | '5' | '6'| '7' | '8' | '9'  {
                 decimal /= 10f;
                 total += (((c as int) - ('0' as int)) as float)*decimal;
             }
             'e' | 'E' {
                 break;
             }
             _ {
                 ret none;
             }
         }
      }
   }

   if (c == 'e') | (c == 'E') {//Examine exponent
      let exponent = 0u;
      let neg_exponent = false;
      if(pos < len) {
          let char_range = str::char_range_at(num, pos);
          c   = char_range.ch;
          alt c  {
             '+' {
                pos = char_range.next;
             }
             '-' {
                pos = char_range.next;
                neg_exponent = true;
             }
             _ {}
          }
          while(pos < len) {
             let char_range = str::char_range_at(num, pos);
             c = char_range.ch;
             alt c {
                 '0' | '1' | '2' | '3' | '4' | '5' | '6'| '7' | '8' | '9' {
                     exponent *= 10u;
                     exponent += ((c as uint) - ('0' as uint));
                 }
                 _ {
                     break;
                 }
             }
             pos = char_range.next;
          }
          let multiplier = pow_uint_to_uint_as_float(10u, exponent);
              //Note: not [int::pow], otherwise, we'll quickly
              //end up with a nice overflow
          if neg_exponent {
             total = total / multiplier;
          } else {
             total = total * multiplier;
          }
      } else {
         ret none;
      }
   }

   if(pos < len) {
     ret none;
   } else {
     if(neg) {
        total *= -1f;
     }
     ret some(total);
   }
}

/**
 * Section: Arithmetics
 */

/*
Function: pow_uint_to_uint_as_float

Compute the exponentiation of an integer by another integer as a float.

Parameters:
x - The base.
pow - The exponent.

Returns:
<NaN> of both `x` and `pow` are `0u`, otherwise `x^pow`.
*/
fn pow_uint_to_uint_as_float(x: uint, pow: uint) -> float {
   if x == 0u {
      if pow == 0u {
        ret NaN;
      }
       ret 0.;
   }
   let my_pow     = pow;
   let total      = 1f;
   let multiplier = x as float;
   while (my_pow > 0u) {
     if my_pow % 2u == 1u {
       total = total * multiplier;
     }
     my_pow     /= 2u;
     multiplier *= multiplier;
   }
   ret total;
}

#[test]
fn test_from_str() {
   assert from_str("3") == some(3.);
   assert from_str("3") == some(3.);
   assert from_str("3.14") == some(3.14);
   assert from_str("+3.14") == some(3.14);
   assert from_str("-3.14") == some(-3.14);
   assert from_str("2.5E10") == some(25000000000.);
   assert from_str("2.5e10") == some(25000000000.);
   assert from_str("25000000000.E-10") == some(2.5);
   assert from_str(".") == some(0.);
   assert from_str(".e1") == some(0.);
   assert from_str(".e-1") == some(0.);
   assert from_str("5.") == some(5.);
   assert from_str(".5") == some(0.5);
   assert from_str("0.5") == some(0.5);
   assert from_str("0.5") == some(0.5);
   assert from_str("0.5") == some(0.5);
   assert from_str("-.5") == some(-0.5);
   assert from_str("-.5") == some(-0.5);
   assert from_str("-5") == some(-5.);

   assert from_str("") == none;
   assert from_str("x") == none;
   assert from_str(" ") == none;
   assert from_str("   ") == none;
   assert from_str("e") == none;
   assert from_str("E") == none;
   assert from_str("E1") == none;
   assert from_str("1e1e1") == none;
   assert from_str("1e1.1") == none;
   assert from_str("1e1-1") == none;
}

#[test]
fn test_positive() {
  assert(is_positive(infinity));
  assert(is_positive(1.));
  assert(is_positive(0.));
  assert(!is_positive(-1.));
  assert(!is_positive(neg_infinity));
  assert(!is_positive(1./neg_infinity));
  assert(!is_positive(NaN));
}

#[test]
fn test_negative() {
  assert(!is_negative(infinity));
  assert(!is_negative(1.));
  assert(!is_negative(0.));
  assert(is_negative(-1.));
  assert(is_negative(neg_infinity));
  assert(is_negative(1./neg_infinity));
  assert(!is_negative(NaN));
}

#[test]
fn test_nonpositive() {
  assert(!is_nonpositive(infinity));
  assert(!is_nonpositive(1.));
  assert(!is_nonpositive(0.));
  assert(is_nonpositive(-1.));
  assert(is_nonpositive(neg_infinity));
  assert(is_nonpositive(1./neg_infinity));
  assert(!is_nonpositive(NaN));
}

#[test]
fn test_nonnegative() {
  assert(is_nonnegative(infinity));
  assert(is_nonnegative(1.));
  assert(is_nonnegative(0.));
  assert(!is_nonnegative(-1.));
  assert(!is_nonnegative(neg_infinity));
  assert(!is_nonnegative(1./neg_infinity));
  assert(!is_nonnegative(NaN));
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//

<commit_msg>expose float::pow_with_uint.<commit_after>#[doc = "Operations and constants for `float`"];

/*
Module: float
*/

// FIXME find out why these have to be exported explicitly

export to_str_common, to_str_exact, to_str, from_str;
export add, sub, mul, div, rem, lt, le, gt, eq, eq, ne;
export is_positive, is_negative, is_nonpositive, is_nonnegative;
export is_zero, is_infinite, is_finite;
export NaN, is_NaN, infinity, neg_infinity;
export consts;
export logarithm;
export acos, asin, atan, atan2, cbrt, ceil, copysign, cos, cosh, floor;
export erf, erfc, exp, expm1, exp2, abs, abs_sub;
export mul_add, fmax, fmin, nextafter, frexp, hypot, ldexp;
export lgamma, ln, log_radix, ln1p, log10, log2, ilog_radix;
export modf, pow, round, sin, sinh, sqrt, tan, tanh, tgamma, trunc;
export signbit;
export pow_with_uint;

// export when m_float == c_double

export j0, j1, jn, y0, y1, yn;

// PORT this must match in width according to architecture

import m_float = f64;
import f64::*;

type t = float;

/**
 * Section: String Conversions
 */

/*
Function: to_str_common

Converts a float to a string

Parameters:

num - The float value
digits - The number of significant digits
exact - Whether to enforce the exact number of significant digits
*/
fn to_str_common(num: float, digits: uint, exact: bool) -> str {
    if is_NaN(num) { ret "NaN"; }
    let (num, accum) = if num < 0.0 { (-num, "-") } else { (num, "") };
    let trunc = num as uint;
    let frac = num - (trunc as float);
    accum += uint::str(trunc);
    if (frac < epsilon && !exact) || digits == 0u { ret accum; }
    accum += ".";
    let i = digits;
    let epsilon = 1. / pow_with_uint(10u, i);
    while i > 0u && (frac >= epsilon || exact) {
        frac *= 10.0;
        epsilon *= 10.0;
        let digit = frac as uint;
        accum += uint::str(digit);
        frac -= digit as float;
        i -= 1u;
    }
    ret accum;

}

/*
Function: to_str

Converts a float to a string with exactly the number of provided significant
digits

Parameters:

num - The float value
digits - The number of significant digits
*/
fn to_str_exact(num: float, digits: uint) -> str {
    to_str_common(num, digits, true)
}

#[test]
fn test_to_str_exact_do_decimal() {
    let s = to_str_exact(5.0, 4u);
    assert s == "5.0000";
}

/*
Function: to_str

Converts a float to a string with a maximum number of significant digits

Parameters:

num - The float value
digits - The number of significant digits
*/
fn to_str(num: float, digits: uint) -> str {
    to_str_common(num, digits, false)
}

/*
Function: from_str

Convert a string to a float

This function accepts strings such as
* "3.14"
* "+3.14", equivalent to "3.14"
* "-3.14"
* "2.5E10", or equivalently, "2.5e10"
* "2.5E-10"
* "", or, equivalently, "." (understood as 0)
* "5."
* ".5", or, equivalently,  "0.5"

Leading and trailing whitespace are ignored.

Parameters:

num - A string

Returns:

none if the string did not represent a valid number.
Otherwise, some(n) where n is the floating-point
number represented by [num].
*/
fn from_str(num: str) -> option<float> {
   let pos = 0u;                  //Current byte position in the string.
                                  //Used to walk the string in O(n).
   let len = str::len(num);  //Length of the string, in bytes.

   if len == 0u { ret none; }
   let total = 0f;                //Accumulated result
   let c     = 'z';               //Latest char.

   //The string must start with one of the following characters.
   alt str::char_at(num, 0u) {
      '-' | '+' | '0' to '9' | '.' {}
      _ { ret none; }
   }

   //Determine if first char is '-'/'+'. Set [pos] and [neg] accordingly.
   let neg = false;               //Sign of the result
   alt str::char_at(num, 0u) {
      '-' {
          neg = true;
          pos = 1u;
      }
      '+' {
          pos = 1u;
      }
      _ {}
   }

   //Examine the following chars until '.', 'e', 'E'
   while(pos < len) {
       let char_range = str::char_range_at(num, pos);
       c   = char_range.ch;
       pos = char_range.next;
       alt c {
         '0' to '9' {
           total = total * 10f;
           total += ((c as int) - ('0' as int)) as float;
         }
         '.' | 'e' | 'E' {
           break;
         }
         _ {
           ret none;
         }
       }
   }

   if c == '.' {//Examine decimal part
      let decimal = 1f;
      while(pos < len) {
         let char_range = str::char_range_at(num, pos);
         c = char_range.ch;
         pos = char_range.next;
         alt c {
            '0' | '1' | '2' | '3' | '4' | '5' | '6'| '7' | '8' | '9'  {
                 decimal /= 10f;
                 total += (((c as int) - ('0' as int)) as float)*decimal;
             }
             'e' | 'E' {
                 break;
             }
             _ {
                 ret none;
             }
         }
      }
   }

   if (c == 'e') | (c == 'E') {//Examine exponent
      let exponent = 0u;
      let neg_exponent = false;
      if(pos < len) {
          let char_range = str::char_range_at(num, pos);
          c   = char_range.ch;
          alt c  {
             '+' {
                pos = char_range.next;
             }
             '-' {
                pos = char_range.next;
                neg_exponent = true;
             }
             _ {}
          }
          while(pos < len) {
             let char_range = str::char_range_at(num, pos);
             c = char_range.ch;
             alt c {
                 '0' | '1' | '2' | '3' | '4' | '5' | '6'| '7' | '8' | '9' {
                     exponent *= 10u;
                     exponent += ((c as uint) - ('0' as uint));
                 }
                 _ {
                     break;
                 }
             }
             pos = char_range.next;
          }
          let multiplier = pow_with_uint(10u, exponent);
              //Note: not [int::pow], otherwise, we'll quickly
              //end up with a nice overflow
          if neg_exponent {
             total = total / multiplier;
          } else {
             total = total * multiplier;
          }
      } else {
         ret none;
      }
   }

   if(pos < len) {
     ret none;
   } else {
     if(neg) {
        total *= -1f;
     }
     ret some(total);
   }
}

/**
 * Section: Arithmetics
 */

/*
Function: pow_with_uint

Compute the exponentiation of an integer by another integer as a float.

Parameters:
x - The base.
pow - The exponent.

Returns:
<NaN> of both `x` and `pow` are `0u`, otherwise `x^pow`.
*/
fn pow_with_uint(base: uint, pow: uint) -> float {
   if base == 0u {
      if pow == 0u {
        ret NaN;
      }
       ret 0.;
   }
   let my_pow     = pow;
   let total      = 1f;
   let multiplier = base as float;
   while (my_pow > 0u) {
     if my_pow % 2u == 1u {
       total = total * multiplier;
     }
     my_pow     /= 2u;
     multiplier *= multiplier;
   }
   ret total;
}

#[test]
fn test_from_str() {
   assert from_str("3") == some(3.);
   assert from_str("3") == some(3.);
   assert from_str("3.14") == some(3.14);
   assert from_str("+3.14") == some(3.14);
   assert from_str("-3.14") == some(-3.14);
   assert from_str("2.5E10") == some(25000000000.);
   assert from_str("2.5e10") == some(25000000000.);
   assert from_str("25000000000.E-10") == some(2.5);
   assert from_str(".") == some(0.);
   assert from_str(".e1") == some(0.);
   assert from_str(".e-1") == some(0.);
   assert from_str("5.") == some(5.);
   assert from_str(".5") == some(0.5);
   assert from_str("0.5") == some(0.5);
   assert from_str("0.5") == some(0.5);
   assert from_str("0.5") == some(0.5);
   assert from_str("-.5") == some(-0.5);
   assert from_str("-.5") == some(-0.5);
   assert from_str("-5") == some(-5.);

   assert from_str("") == none;
   assert from_str("x") == none;
   assert from_str(" ") == none;
   assert from_str("   ") == none;
   assert from_str("e") == none;
   assert from_str("E") == none;
   assert from_str("E1") == none;
   assert from_str("1e1e1") == none;
   assert from_str("1e1.1") == none;
   assert from_str("1e1-1") == none;
}

#[test]
fn test_positive() {
  assert(is_positive(infinity));
  assert(is_positive(1.));
  assert(is_positive(0.));
  assert(!is_positive(-1.));
  assert(!is_positive(neg_infinity));
  assert(!is_positive(1./neg_infinity));
  assert(!is_positive(NaN));
}

#[test]
fn test_negative() {
  assert(!is_negative(infinity));
  assert(!is_negative(1.));
  assert(!is_negative(0.));
  assert(is_negative(-1.));
  assert(is_negative(neg_infinity));
  assert(is_negative(1./neg_infinity));
  assert(!is_negative(NaN));
}

#[test]
fn test_nonpositive() {
  assert(!is_nonpositive(infinity));
  assert(!is_nonpositive(1.));
  assert(!is_nonpositive(0.));
  assert(is_nonpositive(-1.));
  assert(is_nonpositive(neg_infinity));
  assert(is_nonpositive(1./neg_infinity));
  assert(!is_nonpositive(NaN));
}

#[test]
fn test_nonnegative() {
  assert(is_nonnegative(infinity));
  assert(is_nonnegative(1.));
  assert(is_nonnegative(0.));
  assert(!is_nonnegative(-1.));
  assert(!is_nonnegative(neg_infinity));
  assert(!is_nonnegative(1./neg_infinity));
  assert(!is_nonnegative(NaN));
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//

<|endoftext|>


<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(syntax)]
extern mod fourcc;

fn main() {
    let val = fourcc!("\xC0\xFF\xEE!")
    // val is 0xC0FFEE21
    let big_val = fourcc!("foo ", big);
    // big_val is 0x21EEFFC0
}
 ```

# References

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

*/

#[crate_id = "fourcc#0.10-pre"];
#[crate_type = "rlib"];
#[crate_type = "dylib"];
#[license = "MIT/ASL2"];

#[feature(macro_registrar, managed_boxes)];

extern mod syntax;

use syntax::ast;
use syntax::ast::Name;
use syntax::attr::contains;
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MRExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse;
use syntax::parse::token;
use syntax::parse::token::InternedString;

#[macro_registrar]
#[cfg(not(test))]
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
    register(token::intern("fourcc"),
        NormalTT(~BasicMacroExpander {
            expander: expand_syntax_ext,
            span: None,
        },
        None));
}

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

    let little = match endian {
        None => false,
        Some(Ident{ident, span}) => match token::get_ident(ident.name).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(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 MRExpr(cx.expr_lit(sp, ast::LitUint(0u64, ast::TyU32)));
            }
        },
        _ => {
            cx.span_err(expr.span, "non-literal in fourcc!");
            return MRExpr(cx.expr_lit(sp, ast::LitUint(0u64, ast::TyU32)));
        }
    };

    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::LitUint(val as u64, ast::TyU32));
    MRExpr(e)
}

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

fn parse_tts(cx: &ExtCtxt, tts: &[ast::TokenTree]) -> (@ast::Expr, Option<Ident>) {
    let p = &mut parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts.to_owned());
    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(), meta)
}

// Fixes LLVM assert on Windows
#[test]
fn dummy_test() { }
<commit_msg>Fixed fourcc example doc<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(syntax)]
extern mod 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_id = "fourcc#0.10-pre"];
#[crate_type = "rlib"];
#[crate_type = "dylib"];
#[license = "MIT/ASL2"];

#[feature(macro_registrar, managed_boxes)];

extern mod syntax;

use syntax::ast;
use syntax::ast::Name;
use syntax::attr::contains;
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MRExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse;
use syntax::parse::token;
use syntax::parse::token::InternedString;

#[macro_registrar]
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
    register(token::intern("fourcc"),
        NormalTT(~BasicMacroExpander {
            expander: expand_syntax_ext,
            span: None,
        },
        None));
}

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

    let little = match endian {
        None => false,
        Some(Ident{ident, span}) => match token::get_ident(ident.name).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(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 MRExpr(cx.expr_lit(sp, ast::LitUint(0u64, ast::TyU32)));
            }
        },
        _ => {
            cx.span_err(expr.span, "non-literal in fourcc!");
            return MRExpr(cx.expr_lit(sp, ast::LitUint(0u64, ast::TyU32)));
        }
    };

    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::LitUint(val as u64, ast::TyU32));
    MRExpr(e)
}

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

fn parse_tts(cx: &ExtCtxt, tts: &[ast::TokenTree]) -> (@ast::Expr, Option<Ident>) {
    let p = &mut parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts.to_owned());
    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(), meta)
}

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


<commit_before><commit_msg>Remove old TODO<commit_after><|endoftext|>


<commit_before><commit_msg>Fix Timer Services<commit_after><|endoftext|>


<commit_before>use std::str;
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashSet;
use std::net::SocketAddr;
use std::borrow::Borrow;
use std::sync::mpsc;

use futures::Future;
use futures::future;
use futures::future::Loop;
use tokio_core::reactor::Handle;

use trust_dns::client::{ClientFuture, BasicClientHandle, ClientHandle};
use trust_dns::udp::UdpClientStream;
use trust_dns::error::ClientError;
use trust_dns::rr::domain::Name;
use trust_dns::rr::record_type::RecordType;
use trust_dns::rr::dns_class::DNSClass;
use trust_dns::rr::resource::Record;
use trust_dns::op::message::Message;
use trust_dns::error::ClientErrorKind;

use resolve::error::*;
use resolve::batch::{ResolveStatus, QueryType};
use config::CONFIG;

fn make_client(loop_handle: Handle, name_server: SocketAddr) -> BasicClientHandle {
    let (stream, stream_handle) = UdpClientStream::new(
        name_server, loop_handle.clone()
    );

    ClientFuture::new(
        stream,
        stream_handle,
        loop_handle,
        None
    )
}

#[derive(Clone)]
struct ClientFactory {
    loop_handle: Handle,
    name_server: SocketAddr,
}

impl ClientFactory {
    pub fn new(loop_handle: Handle, name_server: SocketAddr) -> ClientFactory {
        ClientFactory {
            loop_handle: loop_handle,
            name_server: name_server,
        }
    }

    fn new_client(&self) -> BasicClientHandle {
        make_client(self.loop_handle.clone(), self.name_server)
    }

    fn dns(&self) -> SocketAddr {
        self.name_server
    }
}

pub struct TrustDNSResolver {
    loop_handle: Handle,
    done_tx: mpsc::Sender<ResolveStatus>,
}

impl TrustDNSResolver {
    pub fn new(loop_handle: Handle, done_tx: mpsc::Sender<ResolveStatus>) -> Self {
        TrustDNSResolver {
            loop_handle: loop_handle.clone(),
            done_tx: done_tx
        }
    }
}

impl TrustDNSResolver {
    pub fn resolve(&self, dns: SocketAddr, name: &str, query_type: QueryType)
        -> Box<Future<Item=Vec<String>, Error=ResolverError>>
    {
        let client_factory = ClientFactory::new(self.loop_handle.clone(), dns);

        self.done_tx.send(ResolveStatus::Started).unwrap();
        let done_tx = self.done_tx.clone();

        let future = match query_type {
            QueryType::PTR => self.reverse_resolve(client_factory, name),
            _              => self.simple_resolve(client_factory, name, query_type.into()),
        };

        let name = name.to_owned();
        let future = future.map(move |msg| msg.extract_answer(query_type))
            .then(move |rv| rv.report_status(&name, done_tx))
            .then(move |rv| rv.partial_ok());

        Box::new(future)
    }

    fn simple_resolve(&self, client_factory: ClientFactory, name: &str, rtype: RecordType)
        -> Box<Future<Item=Message, Error=ResolverError>>
    {
        Box::new(
            Self::resolve_retry(
                client_factory,
                Name::parse(&name, Some(&Name::root())).unwrap(),
                DNSClass::IN,
                rtype,
        ))
    }

    fn reverse_resolve(&self, client_factory: ClientFactory, ip: &str) -> Box<Future<Item=Message, Error=ResolverError>> {
        let mut labels = ip.split('.').map(str::to_owned).collect::<Vec<_>>();
        labels.reverse();

        let name = Name::with_labels(labels).label("in-addr").label("arpa");

        Box::new(
            self.recurse_ptr(
                client_factory,
                name,
                DNSClass::IN,
                RecordType::PTR,
        ))
    }

    fn recurse_ptr(&self, client_factory: ClientFactory, name: Name, query_class: DNSClass, query_type: RecordType)
        -> Box<Future<Item=Message, Error=ResolverError>>
    {
        struct State {
            handle: Handle,
            client_factory: ClientFactory,
            nameservers: Vec<NS>,
            visited: HashSet<NS>,
            answer: Option<Message>
        }

        impl State {
            pub fn pop_ns(&mut self) -> Option<NS> {
                self.nameservers.pop().map(|ns| {
                    self.visited.insert(ns.clone());
                    ns
                })
            }

            pub fn push_nameservers<I, B>(&mut self, iter: I)
                where I: IntoIterator<Item=B>,
                    B: Borrow<Name>
            {
                let new_nameservers = iter.into_iter()
                    .map(NS::try_from)
                    .filter_map(Result::ok)
                    .filter(|ns| !self.visited.contains(ns))
                    .collect::<Vec<_>>();
                self.nameservers.extend(new_nameservers)
            }

            pub fn add_answer(&mut self, answer: Message) {
                self.answer = Some(answer)
            }
        }

        let state = State {
            handle: self.loop_handle.clone(),
            client_factory: client_factory.clone(),
            nameservers: vec![NS::Known(client_factory.dns())],
            visited: HashSet::new(),
            answer: None,
        };

        let resolve_loop = future::loop_fn(state, move |mut state| {
            Self::resolve_with_ns(
                state.handle.clone(),
                state.client_factory.clone(),
                state.pop_ns().unwrap(),
                name.clone(), query_class, query_type
            ).map(move |message| {
                state.push_nameservers(message.name_servers().iter().map(Record::name));
                state.add_answer(message);
                state
            })
            .and_then(|state| {
                if !state.answer.is_none() || state.nameservers.is_empty() {
                    Ok(Loop::Break(state))
                } else {
                    Ok(Loop::Continue(state))
                }
            })
        });

        Box::new(resolve_loop.and_then(|state| {
            if let Some(answer) = state.answer {
                Ok(answer)
            } else {
                Err(ResolverError::NotFound)
            }
        }))
    }

    fn resolve_with_ns(loop_handle: Handle, client_factory: ClientFactory, nameserver: NS, name: Name, query_class: DNSClass, query_type: RecordType)
        -> Box<Future<Item=Message, Error=ResolverError>>
    {
        debug!("Resolving {:?} with nameserver {:?}", name.to_string(), nameserver.to_string());
        let ns_resolve: Box<Future<Item=Option<SocketAddr>, Error=ResolverError>> = match nameserver {
            NS::Known(addr) => future::ok(Some(addr)).boxed(),
            NS::Unknown(domain) => {
                Box::new(Self::resolve_retry(
                    client_factory.clone(),
                    Name::parse(&domain, Some(&Name::root())).unwrap(),
                    DNSClass::IN,
                    RecordType::A,
                ).map(|msg| msg.extract_answer(QueryType::A)
                    .into_iter().nth(0)
                    .map(|mut ip| { ip.push_str(":53"); ip } )
                        .and_then(|ip| ip.parse::<SocketAddr>()
                            .map_err(|e| {
                                error!("Invalid IP({:?}): {:?}", ip, e);
                                e
                            })
                            .ok()
                )))
            }
        };

        let future = ns_resolve.then(move |result| {
            match result {
                Ok(Some(nameserver)) => Self::resolve_retry(
                                        ClientFactory::new(loop_handle, nameserver),
                                        name.clone(),
                                        query_class,
                                        query_type),
                Ok(None) => future::err(ResolverError::NameServerNotResolved).boxed(),
                Err(err) => future::err(err).boxed(),

            }
        });

        Box::new(future)
    }

    fn resolve_retry(client_factory: ClientFactory, name: Name, query_class: DNSClass, query_type: RecordType)
        -> Box<Future<Item=Message, Error=ResolverError>>
    {
        struct State(RefCell<u32>, RefCell<Option<Message>>);
        impl State {
            fn new() -> Self {
                State(RefCell::new(CONFIG.read().unwrap().timeout_retries()), RefCell::new(None))
            }

            fn next_step(state: Rc<Self>) -> Result<Loop<Rc<Self>, Rc<Self>>, ResolverError> {
                *state.0.borrow_mut() -= 1;
                if *state.0.borrow() > 0 {
                    Ok(Loop::Continue(state))
                } else {
                    Ok(Loop::Break(state))
                }
            }

            fn has_next_step(state: &Rc<Self>) -> bool {
                *state.0.borrow() > 0
            }

            fn set_message(state: &Rc<Self>, message: Option<Message>) {
                *state.1.borrow_mut() = message
            }

            fn get_message(state: &Rc<Self>) -> Option<Message> {
                state.1.borrow().clone()
            }
        }

        let state = Rc::new(State::new());

        let retry_loop = {
            let name = name.clone();

            future::loop_fn(state, move |state| {
                let and_state = state.clone();
                let or_state = state.clone();
                Self::_resolve(client_factory.new_client(), name.clone(), query_class, query_type)
                    .then(move |result| match result {
                        Ok(message) => {
                            trace!("Received DNS message: {:?}", message.answers());
                            State::set_message(&state, Some(message));
                            Ok(Loop::Break(and_state))
                        },
                        Err(err) => match *err.kind() {
                            ClientErrorKind::Timeout => {
                                State::next_step(or_state)
                            },
                            ClientErrorKind::Canceled(e) => {
                                if !State::has_next_step(&or_state) {error!("{}", e)}
                                State::next_step(or_state)
                            },
                            _  => Err(ResolverError::DnsClientError(err))
                        },
                    }
                )
            })
        };

        let future = retry_loop.then(move |result| {
            match result {
                Ok(state) => {
                    let message = State::get_message(&state);
                    match message {
                        Some(message) => Ok(message),
                        None     => Err(ResolverError::ConnectionTimeout),
                    }
                },
                Err(err) => Err(err)
            }
        });

        Box::new(future)
    }

    fn _resolve(mut client: BasicClientHandle, name: Name, query_class: DNSClass, query_type: RecordType)
        -> Box<Future<Item=Message, Error=ClientError>>
    {
        Box::new(
            client.query(
                name,
                query_class,
                query_type
            )
        )
    }
}

use trust_dns::rr::RData;

trait FromRecord<B>
    where B: Borrow<Record>,
          Self: Sized
{
    fn from(r: B, qtype: QueryType) -> Option<Self>;
}

impl<B> FromRecord<B> for String
    where B: Borrow<Record>
{
    fn from(r: B, qtype: QueryType) -> Option<Self> {
        let r = r.borrow();

        macro_rules! variants_to_string {
            ($($x:tt),*) => {
                match (qtype, r.rdata()) {
                    $(
                        (QueryType::$x, &RData::$x(ref data)) => Some(data.to_string()),
                    )*
                    _ => None
                }
            }
        }

        variants_to_string!(
            A,
            AAAA,
            NS,
            PTR
        )
    }
}

trait ExtractAnswer {
    fn extract_answer(&self, qtype: QueryType) -> Vec<String>;
}

impl ExtractAnswer for Message {
    fn extract_answer(&self, qtype: QueryType) -> Vec<String> {
        self.answers().into_iter()
            .map(|record| <String as FromRecord<_>>::from(record, qtype))
            .filter(Option::is_some)
            .map(Option::unwrap)
            .collect()
    }
}

trait ReportStatus {
    fn report_status(self, name: &str, done_tx: mpsc::Sender<ResolveStatus>) -> Self;
}

impl<T> ReportStatus for Result<Vec<T>, ResolverError> {
    fn report_status(self, name: &str, done_tx: mpsc::Sender<ResolveStatus>) -> Self {
        match self.as_ref() {
            Ok(vec) => if vec.is_empty() {
                done_tx.send(ResolveStatus::Failure).unwrap();
            } else {
                done_tx.send(ResolveStatus::Success).unwrap();
            },
            Err(error) => {
                match *error {
                    ResolverError::ConnectionTimeout |
                    ResolverError::NameServerNotResolved => {
                        debug!("failed to resolve {:?}: {}", name, error);
                        done_tx.send(ResolveStatus::Failure).unwrap();
                    }
                    _ => {
                        error!("failed to resolve {:?}: {}", name, error);
                        done_tx.send(ResolveStatus::Error).unwrap();
                    }
                }
            }
        }
        self
    }
}

trait PartialOk<T> {
    fn partial_ok(self) -> Result<Vec<T>, ResolverError>;
}

impl<T> PartialOk<T> for Result<Vec<T>, ResolverError> {
    fn partial_ok(self) -> Result<Vec<T>, ResolverError> {
        match self {
            Err(ResolverError::ConnectionTimeout) |
            Err(ResolverError::NameServerNotResolved) |
            Err(ResolverError::NotFound)
                     => Ok(vec![]),
            Ok(vec)  => Ok(vec),
            Err(err) => Err(err)
        }
    }
}

#[derive(Debug, Hash, Eq, PartialEq, Clone)]
enum NS {
    Known(SocketAddr),
    Unknown(String)
}

impl NS {
    pub fn to_string(&self) -> String {
        match *self {
            NS::Known(ref addr) => addr.to_string(),
            NS::Unknown(ref dom) => dom.clone()
        }
    }

    pub fn try_from<B>(name: B) -> Result<NS, ()>
        where B: Borrow<Name>
    {
        let name = name.borrow();
        if name.num_labels() != 0 {
            Ok(NS::Unknown(name.to_string()))
        } else {
            Err(())
        }
    }
}

impl From<SocketAddr> for NS {
    fn from(addr: SocketAddr) -> NS {
        NS::Known(addr)
    }
}<commit_msg>Got rid of Rc<Refcell<T>> in resolve loop<commit_after>use std::str;
use std::cell::Cell;
use std::collections::HashSet;
use std::net::SocketAddr;
use std::borrow::Borrow;
use std::sync::mpsc;

use futures::Future;
use futures::future;
use futures::future::Loop;
use tokio_core::reactor::Handle;

use trust_dns::client::{ClientFuture, BasicClientHandle, ClientHandle};
use trust_dns::udp::UdpClientStream;
use trust_dns::error::ClientError;
use trust_dns::rr::domain::Name;
use trust_dns::rr::record_type::RecordType;
use trust_dns::rr::dns_class::DNSClass;
use trust_dns::rr::resource::Record;
use trust_dns::op::message::Message;
use trust_dns::error::ClientErrorKind;

use resolve::error::*;
use resolve::batch::{ResolveStatus, QueryType};
use config::CONFIG;

fn make_client(loop_handle: Handle, name_server: SocketAddr) -> BasicClientHandle {
    let (stream, stream_handle) = UdpClientStream::new(
        name_server, loop_handle.clone()
    );

    ClientFuture::new(
        stream,
        stream_handle,
        loop_handle,
        None
    )
}

#[derive(Clone)]
struct ClientFactory {
    loop_handle: Handle,
    name_server: SocketAddr,
}

impl ClientFactory {
    pub fn new(loop_handle: Handle, name_server: SocketAddr) -> ClientFactory {
        ClientFactory {
            loop_handle: loop_handle,
            name_server: name_server,
        }
    }

    fn new_client(&self) -> BasicClientHandle {
        make_client(self.loop_handle.clone(), self.name_server)
    }

    fn dns(&self) -> SocketAddr {
        self.name_server
    }
}

pub struct TrustDNSResolver {
    loop_handle: Handle,
    done_tx: mpsc::Sender<ResolveStatus>,
}

impl TrustDNSResolver {
    pub fn new(loop_handle: Handle, done_tx: mpsc::Sender<ResolveStatus>) -> Self {
        TrustDNSResolver {
            loop_handle: loop_handle.clone(),
            done_tx: done_tx
        }
    }
}

impl TrustDNSResolver {
    pub fn resolve(&self, dns: SocketAddr, name: &str, query_type: QueryType)
        -> Box<Future<Item=Vec<String>, Error=ResolverError>>
    {
        let client_factory = ClientFactory::new(self.loop_handle.clone(), dns);

        self.done_tx.send(ResolveStatus::Started).unwrap();
        let done_tx = self.done_tx.clone();

        let future = match query_type {
            QueryType::PTR => self.reverse_resolve(client_factory, name),
            _              => self.simple_resolve(client_factory, name, query_type.into()),
        };

        let name = name.to_owned();
        let future = future.map(move |msg| msg.extract_answer(query_type))
            .then(move |rv| rv.report_status(&name, done_tx))
            .then(move |rv| rv.partial_ok());

        Box::new(future)
    }

    fn simple_resolve(&self, client_factory: ClientFactory, name: &str, rtype: RecordType)
        -> Box<Future<Item=Message, Error=ResolverError>>
    {
        Box::new(
            Self::resolve_retry(
                client_factory,
                Name::parse(&name, Some(&Name::root())).unwrap(),
                DNSClass::IN,
                rtype,
        ))
    }

    fn reverse_resolve(&self, client_factory: ClientFactory, ip: &str) -> Box<Future<Item=Message, Error=ResolverError>> {
        let mut labels = ip.split('.').map(str::to_owned).collect::<Vec<_>>();
        labels.reverse();

        let name = Name::with_labels(labels).label("in-addr").label("arpa");

        Box::new(
            self.recurse_ptr(
                client_factory,
                name,
                DNSClass::IN,
                RecordType::PTR,
        ))
    }

    fn recurse_ptr(&self, client_factory: ClientFactory, name: Name, query_class: DNSClass, query_type: RecordType)
        -> Box<Future<Item=Message, Error=ResolverError>>
    {
        struct State {
            handle: Handle,
            client_factory: ClientFactory,
            nameservers: Vec<NS>,
            visited: HashSet<NS>,
            answer: Option<Message>
        }

        impl State {
            pub fn pop_ns(&mut self) -> Option<NS> {
                self.nameservers.pop().map(|ns| {
                    self.visited.insert(ns.clone());
                    ns
                })
            }

            pub fn push_nameservers<I, B>(&mut self, iter: I)
                where I: IntoIterator<Item=B>,
                    B: Borrow<Name>
            {
                let new_nameservers = iter.into_iter()
                    .map(NS::try_from)
                    .filter_map(Result::ok)
                    .filter(|ns| !self.visited.contains(ns))
                    .collect::<Vec<_>>();
                self.nameservers.extend(new_nameservers)
            }

            pub fn add_answer(&mut self, answer: Message) {
                self.answer = Some(answer)
            }
        }

        let state = State {
            handle: self.loop_handle.clone(),
            client_factory: client_factory.clone(),
            nameservers: vec![NS::Known(client_factory.dns())],
            visited: HashSet::new(),
            answer: None,
        };

        let resolve_loop = future::loop_fn(state, move |mut state| {
            Self::resolve_with_ns(
                state.handle.clone(),
                state.client_factory.clone(),
                state.pop_ns().unwrap(),
                name.clone(), query_class, query_type
            ).map(move |message| {
                state.push_nameservers(message.name_servers().iter().map(Record::name));
                state.add_answer(message);
                state
            })
            .and_then(|state| {
                if !state.answer.is_none() || state.nameservers.is_empty() {
                    Ok(Loop::Break(state))
                } else {
                    Ok(Loop::Continue(state))
                }
            })
        });

        Box::new(resolve_loop.and_then(|state| {
            if let Some(answer) = state.answer {
                Ok(answer)
            } else {
                Err(ResolverError::NotFound)
            }
        }))
    }

    fn resolve_with_ns(loop_handle: Handle, client_factory: ClientFactory, nameserver: NS, name: Name, query_class: DNSClass, query_type: RecordType)
        -> Box<Future<Item=Message, Error=ResolverError>>
    {
        debug!("Resolving {:?} with nameserver {:?}", name.to_string(), nameserver.to_string());
        let ns_resolve: Box<Future<Item=Option<SocketAddr>, Error=ResolverError>> = match nameserver {
            NS::Known(addr) => future::ok(Some(addr)).boxed(),
            NS::Unknown(domain) => {
                Box::new(Self::resolve_retry(
                    client_factory.clone(),
                    Name::parse(&domain, Some(&Name::root())).unwrap(),
                    DNSClass::IN,
                    RecordType::A,
                ).map(|msg| msg.extract_answer(QueryType::A)
                    .into_iter().nth(0)
                    .map(|mut ip| { ip.push_str(":53"); ip } )
                        .and_then(|ip| ip.parse::<SocketAddr>()
                            .map_err(|e| {
                                error!("Invalid IP({:?}): {:?}", ip, e);
                                e
                            })
                            .ok()
                )))
            }
        };

        let future = ns_resolve.then(move |result| {
            match result {
                Ok(Some(nameserver)) => Self::resolve_retry(
                                        ClientFactory::new(loop_handle, nameserver),
                                        name.clone(),
                                        query_class,
                                        query_type),
                Ok(None) => future::err(ResolverError::NameServerNotResolved).boxed(),
                Err(err) => future::err(err).boxed(),

            }
        });

        Box::new(future)
    }

    fn resolve_retry(client_factory: ClientFactory, name: Name, query_class: DNSClass, query_type: RecordType)
        -> Box<Future<Item=Message, Error=ResolverError>>
    {
        struct State {
            tries_left: Cell<u32>,
            message: Cell<Option<Message>>
        };

        impl State {
            fn new() -> Self {
                State {
                    tries_left: Cell::new(CONFIG.read().unwrap().timeout_retries()),
                    message: Cell::new(None)
                }
            }

            fn next_step(self) -> Result<Loop<Self, Self>, ResolverError> {
                let old_value = self.tries_left.get();
                self.tries_left.set(old_value - 1);

                if self.tries_left.get() > 0 {
                    Ok(Loop::Continue(self))
                } else {
                    Ok(Loop::Break(self))
                }
            }

            fn has_next_step(&self) -> bool {
                self.tries_left.get() > 0
            }

            fn set_message(&self, message: Option<Message>) {
                self.message.set(message)
            }

            fn into_message(self) -> Option<Message> {
                self.message.into_inner()
            }
        }

        let state = State::new();

        let retry_loop = {
            let name = name.clone();

            future::loop_fn(state, move |state| {
                Self::_resolve(client_factory.new_client(), name.clone(), query_class, query_type)
                    .then(move |result| match result {
                        Ok(message) => {
                            trace!("Received DNS message: {:?}", message.answers());
                            state.set_message(Some(message));
                            Ok(Loop::Break(state))
                        },
                        Err(err) => match *err.kind() {
                            ClientErrorKind::Timeout => {
                                state.next_step()
                            },
                            ClientErrorKind::Canceled(e) => {
                                if !state.has_next_step() {error!("{}", e)}
                                state.next_step()
                            },
                            _  => Err(ResolverError::DnsClientError(err))
                        },
                    }
                )
            })
        };

        let future = retry_loop.then(move |result| {
            match result {
                Ok(state) => {
                    let message = state.into_message();
                    match message {
                        Some(message) => Ok(message),
                        None     => Err(ResolverError::ConnectionTimeout),
                    }
                },
                Err(err) => Err(err)
            }
        });

        Box::new(future)
    }

    fn _resolve(mut client: BasicClientHandle, name: Name, query_class: DNSClass, query_type: RecordType)
        -> Box<Future<Item=Message, Error=ClientError>>
    {
        Box::new(
            client.query(
                name,
                query_class,
                query_type
            )
        )
    }
}

use trust_dns::rr::RData;

trait FromRecord<B>
    where B: Borrow<Record>,
          Self: Sized
{
    fn from(r: B, qtype: QueryType) -> Option<Self>;
}

impl<B> FromRecord<B> for String
    where B: Borrow<Record>
{
    fn from(r: B, qtype: QueryType) -> Option<Self> {
        let r = r.borrow();

        macro_rules! variants_to_string {
            ($($x:tt),*) => {
                match (qtype, r.rdata()) {
                    $(
                        (QueryType::$x, &RData::$x(ref data)) => Some(data.to_string()),
                    )*
                    _ => None
                }
            }
        }

        variants_to_string!(
            A,
            AAAA,
            NS,
            PTR
        )
    }
}

trait ExtractAnswer {
    fn extract_answer(&self, qtype: QueryType) -> Vec<String>;
}

impl ExtractAnswer for Message {
    fn extract_answer(&self, qtype: QueryType) -> Vec<String> {
        self.answers().into_iter()
            .map(|record| <String as FromRecord<_>>::from(record, qtype))
            .filter(Option::is_some)
            .map(Option::unwrap)
            .collect()
    }
}

trait ReportStatus {
    fn report_status(self, name: &str, done_tx: mpsc::Sender<ResolveStatus>) -> Self;
}

impl<T> ReportStatus for Result<Vec<T>, ResolverError> {
    fn report_status(self, name: &str, done_tx: mpsc::Sender<ResolveStatus>) -> Self {
        match self.as_ref() {
            Ok(vec) => if vec.is_empty() {
                done_tx.send(ResolveStatus::Failure).unwrap();
            } else {
                done_tx.send(ResolveStatus::Success).unwrap();
            },
            Err(error) => {
                match *error {
                    ResolverError::ConnectionTimeout |
                    ResolverError::NameServerNotResolved => {
                        debug!("failed to resolve {:?}: {}", name, error);
                        done_tx.send(ResolveStatus::Failure).unwrap();
                    }
                    _ => {
                        error!("failed to resolve {:?}: {}", name, error);
                        done_tx.send(ResolveStatus::Error).unwrap();
                    }
                }
            }
        }
        self
    }
}

trait PartialOk<T> {
    fn partial_ok(self) -> Result<Vec<T>, ResolverError>;
}

impl<T> PartialOk<T> for Result<Vec<T>, ResolverError> {
    fn partial_ok(self) -> Result<Vec<T>, ResolverError> {
        match self {
            Err(ResolverError::ConnectionTimeout) |
            Err(ResolverError::NameServerNotResolved) |
            Err(ResolverError::NotFound)
                     => Ok(vec![]),
            Ok(vec)  => Ok(vec),
            Err(err) => Err(err)
        }
    }
}

#[derive(Debug, Hash, Eq, PartialEq, Clone)]
enum NS {
    Known(SocketAddr),
    Unknown(String)
}

impl NS {
    pub fn to_string(&self) -> String {
        match *self {
            NS::Known(ref addr) => addr.to_string(),
            NS::Unknown(ref dom) => dom.clone()
        }
    }

    pub fn try_from<B>(name: B) -> Result<NS, ()>
        where B: Borrow<Name>
    {
        let name = name.borrow();
        if name.num_labels() != 0 {
            Ok(NS::Unknown(name.to_string()))
        } else {
            Err(())
        }
    }
}

impl From<SocketAddr> for NS {
    fn from(addr: SocketAddr) -> NS {
        NS::Known(addr)
    }
}<|endoftext|>


<commit_before><commit_msg>Add initial basic benchmark for header setters<commit_after>#![feature(test)]

extern crate rips_packets;
extern crate test;

use rips_packets::ethernet::{MutEthernetPacket, ether_types};
use rips_packets::ipv4::{self, MutIpv4Packet};
use rips_packets::macaddr::MacAddr;
use std::net::Ipv4Addr;
use test::{Bencher, black_box};

#[bench]
fn set_all_ethernet_fields(b: &mut Bencher) {
    let mut buffer = [0; 14];
    let source = MacAddr([0xff, 0x00, 0xff, 0x00, 0xff, 0x00]);
    let destination = MacAddr([0x00, 0xff, 0x00, 0xff, 0x00, 0xff]);
    b.iter(|| {
        let mut packet = MutEthernetPacket::new(black_box(&mut buffer[..])).unwrap();
        packet.set_destination(black_box(destination));
        packet.set_source(black_box(source));
        packet.set_ether_type(black_box(ether_types::ARP));
    });
}

#[bench]
fn set_all_ipv4_fields(b: &mut Bencher) {
    let mut buffer = [0; 20];
    let source = Ipv4Addr::new(192, 168, 0, 1);
    let destination = Ipv4Addr::new(192, 168, 0, 2);
    b.iter(|| {
        let mut packet = MutIpv4Packet::new(black_box(&mut buffer[..])).unwrap();
        packet.set_version(black_box(4));
        packet.set_header_length(black_box(5));
        packet.set_dscp(black_box(0));
        packet.set_ecn(black_box(0));
        packet.set_total_length(black_box(20));
        packet.set_identification(black_box(0x1337));
        packet.set_flags(black_box(0b011));
        packet.set_fragment_offset(black_box(13));
        packet.set_ttl(black_box(40));
        packet.set_protocol(black_box(ipv4::protocols::UDP));
        packet.set_header_checksum(black_box(0x1337));
        packet.set_source(black_box(source));
        packet.set_destination(black_box(destination));
    });
}
<|endoftext|>


<commit_before><commit_msg>Lay groundwork for closures<commit_after><|endoftext|>


<commit_before><commit_msg>Set extension or warn if none there<commit_after><|endoftext|>


<commit_before>use redox::ops::DerefMut;
use redox::string::*;
use redox::vec::Vec;
use redox::boxed::Box;
use redox::fs::*;
use redox::io::*;
use redox::console::*;
use redox::env::*;
use redox::time::Duration;
use redox::to_num::*;

/* Magic Macros { */
static mut application: *mut Application<'static> = 0 as *mut Application;

/// Execute a command
macro_rules! exec {
    ($cmd:expr) => ({
        unsafe {
            (*application).on_command(&$cmd.to_string());
        }
    })
}
/* } Magic Macros */

/// A command
pub struct Command<'a> {
    pub name: &'a str,
    pub main: Box<Fn(&Vec<String>)>,
}

impl<'a> Command<'a> {
    /// Return the vector of the commands
    // TODO: Use a more efficient collection instead
    pub fn vec() -> Vec<Self> {
        let mut commands: Vec<Self> = Vec::new();
        commands.push(Command {
            name: "echo",
            main: box |args: &Vec<String>| {
                let echo = args.iter()
                    .skip(1)
                    .fold(String::new(), |string, arg| string + " " + arg);
                println!("{}", echo.trim());
            },
        });

        commands.push(Command {
            name: "open",
            main: box |args: &Vec<String>| {
                if let Some(arg) = args.get(1) {
                    File::exec(arg);
                }
            },
        });

        commands.push(Command {
            name: "run",
            main: box |args: &Vec<String>| {
                if let Some(path) = args.get(1) {

                    let mut commands = String::new();
                    if let Some(mut file) = File::open(path) {
                        println!("URL: {:?}", file.path());

                        file.read_to_string(&mut commands);
                    }

                    for command in commands.split('\n') {
                        exec!(command);
                    }
                }
            },
        });

        commands.push(Command {
            name: "send",
            main: box |args: &Vec<String>| {
                if args.len() < 3 {
                    println!("Error: incorrect arguments");
                    println!("Usage: send [url] [data]");
                    return;
                }

                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let string: String = args.iter()
                        .skip(2)
                        .fold(String::new(), |s, arg| s + " " + arg)
                        + "\r\n\r\n";

                    match file.write(string.trim_left().as_bytes()) {
                        Some(size) => println!("Wrote {} bytes", size),
                        None => println!("Failed to write"),
                    }

                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "sleep",
            main: box |args: &Vec<String>| {
                let secs = {
                    match args.get(1) {
                        Some(arg) => arg.to_num() as i64,
                        None => 0,
                    }
                };

                let nanos = {
                    match args.get(2) {
                        Some(arg) => arg.to_num() as i32,
                        None => 0,
                    }
                };

                println!("Sleep: {} {}", secs, nanos);
                let remaining = Duration::new(secs, nanos).sleep();
                println!("Remaining: {} {}", remaining.secs, remaining.nanos);
            },
        });

        commands.push(Command {
            name: "test_ht",
            main: box |args: &Vec<String>| {
                ::redox::hashmap::test();
            },
        });

        commands.push(Command {
            name: "url",
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "url_hex",
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let mut vec: Vec<u8> = Vec::new();
                    match file.read_to_end(&mut vec) {
                        Some(_) => {
                            let mut line = "HEX:".to_string();
                            for byte in vec.iter() {
                                line = line + " " + &format!("{:X}", *byte);
                            }
                            println!("{}", line);
                        }
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "wget",
            main: box |args: &Vec<String>| {
                if let Some(host) = args.get(1) {
                    if let Some(req) = args.get(2) {
                        if let Some(mut con) = File::open(&("tcp://".to_string() + host)) {
                            con.write(("GET ".to_string() + req + " HTTP/1.1").as_bytes());

                            let mut res = Vec::new();
                            con.read_to_end(&mut res);

                            if let Some(mut file) = File::open(&req) {
                                file.write(&res);
                            }
                        }
                    } else {
                        println!("No request given");
                    }
                } else {
                    println!("No url given");
                }
            },
        });

        // Simple command to create a file, in the current directory
        // The file has got the name given as the first argument of the command
        // If the command have no arguments, the command don't create the file
        commands.push(Command {
            name: "cfile",
            main: box |args: &Vec<String>| {
                match args.get(1) {
                    Some(file_name) => {
                        File::create(file_name);
                    }
                    None => {
                        println!("Could not create a file without a name");
                    }
                }
            }
        });

        commands.push(Command {
            name: "pwd",
            main: box |args: &Vec<String>| {
                let mut err = false;
                if let Some(file) = File::open("") {
                    if let Some(path) = file.path() {
                        println!("{}", path);
                    } else {
                        err = true;
                    }
                } else {
                    err = true;
                }
                if err {
                    println!("Could not get the path");
                }
            },
        });

        commands.push(Command {
            name: "cd",
            main: box |args: &Vec<String>| {
                match args.get(1) {
                    Some(path) => {
                        if !change_cwd(&path) {
                            println!("Bad path: {}", path);
                        }
                    }
                    None => println!("No path given")
                }
            },
        });

        let command_list = commands.iter().fold(String::new(), |l , c| l + " " + c.name) + " exit";

        commands.push(Command {
            name: "help",
            main: box move |args: &Vec<String>| {
                println!("Commands:{}", command_list);
            },
         });

        commands
    }
}

/// A (env) variable
pub struct Variable {
    pub name: String,
    pub value: String,
}

pub struct Mode {
    value: bool,
}

/// An application
pub struct Application<'a> {
    commands: Vec<Command<'a>>,
    variables: Vec<Variable>,
    modes: Vec<Mode>,
}

impl<'a> Application<'a> {
    /// Create a new empty application
    pub fn new() -> Self {
        return Application {
            commands: Command::vec(),
            variables: Vec::new(),
            modes: Vec::new(),
        };
    }

    fn on_command(&mut self, command_string: &str) {
        //Comment
        if command_string.starts_with('#') {
            return;
        }

        //Show variables
        if command_string == "$" {
            let variables = self.variables.iter()
                .fold(String::new(),
                      |string, variable| string + "\n" + &variable.name + "=" + &variable.value);
            println!("{}", variables);
            return;
        }

        //Explode into arguments, replace variables
        let mut args: Vec<String> = Vec::<String>::new();
        for arg in command_string.split(' ') {
            if !arg.is_empty() {
                if arg.starts_with('$') {
                    let name = arg[1 .. arg.len()].to_string();
                    for variable in self.variables.iter() {
                        if variable.name == name {
                            args.push(variable.value.clone());
                            break;
                        }
                    }
                } else {
                    args.push(arg.to_string());
                }
            }
        }

        //Execute commands
        if let Some(cmd) = args.get(0) {
            if cmd == "if" {
                let mut value = false;

                if let Some(left) = args.get(1) {
                    if let Some(cmp) = args.get(2) {
                        if let Some(right) = args.get(3) {
                            if cmp == "==" {
                                value = *left == *right;
                            } else if cmp == "!=" {
                                value = *left != *right;
                            } else if cmp == ">" {
                                value = left.to_num_signed() > right.to_num_signed();
                            } else if cmp == ">=" {
                                value = left.to_num_signed() >= right.to_num_signed();
                            } else if cmp == "<" {
                                value = left.to_num_signed() < right.to_num_signed();
                            } else if cmp == "<=" {
                                value = left.to_num_signed() <= right.to_num_signed();
                            } else {
                                println!("Unknown comparison: {}", cmp);
                            }
                        }
                    }
                }

                self.modes.insert(0, Mode { value: value });
                return;
            }

            if cmd == "else" {
                let mut syntax_error = false;
                match self.modes.get_mut(0) {
                    Some(mode) => mode.value = !mode.value,
                    None => syntax_error = true,
                }
                if syntax_error {
                    println!("Syntax error: else found with no previous if");
                }
                return;
            }

            if cmd == "fi" {
                let mut syntax_error = false;
                if !self.modes.is_empty() {
                    self.modes.remove(0);
                } else {
                    syntax_error = true;
                }
                if syntax_error {
                    println!("Syntax error: fi found with no previous if");
                }
                return;
            }

            for mode in self.modes.iter() {
                if !mode.value {
                    return;
                }
            }

            //Set variables
            if let Some(i) = cmd.find('=') {
                let name = cmd[0 .. i].to_string();
                let mut value = cmd[i + 1 .. cmd.len()].to_string();

                if name.is_empty() {
                    return;
                }

                for i in 1..args.len() {
                    if let Some(arg) = args.get(i) {
                        value = value + " " + &arg;
                    }
                }

                if value.is_empty() {
                    let mut remove = -1;
                    for i in 0..self.variables.len() {
                        match self.variables.get(i) {
                            Some(variable) => if variable.name == name {
                                remove = i as isize;
                                break;
                            },
                            None => break,
                        }
                    }

                    if remove >= 0 {
                        self.variables.remove(remove as usize);
                    }
                } else {
                    for variable in self.variables.iter_mut() {
                        if variable.name == name {
                            variable.value = value;
                            return;
                        }
                    }

                    self.variables.push(Variable {
                        name: name,
                        value: value,
                    });
                }
                return;
            }

            //Commands
            for command in self.commands.iter() {
                if &command.name == cmd {
                    (*command.main)(&args);
                    return;
                }
            }

            println!("Unknown command: '{}'", cmd);
        }
    }

    /// Run the application
    pub fn main(&mut self) {
        console_title("Terminal");

        println!("Type help for a command list");
        if let Some(arg) = args().get(1) {
            let command = "run ".to_string() + arg;
            println!("# {}", command);
            self.on_command(&command);
        }

        while let Some(command) = readln!() {
            println!("# {}", command);
            if command == "exit" {
                break;
            } else if !command.is_empty() {
                self.on_command(&command);
            }
        }
    }
}

pub fn main() {
    unsafe {
        let mut app = box Application::new();
        application = app.deref_mut();
        app.main();
    }
}
<commit_msg>Modification to improve the code for the command 'pwd'<commit_after>use redox::ops::DerefMut;
use redox::string::*;
use redox::vec::Vec;
use redox::boxed::Box;
use redox::fs::*;
use redox::io::*;
use redox::console::*;
use redox::env::*;
use redox::time::Duration;
use redox::to_num::*;

/* Magic Macros { */
static mut application: *mut Application<'static> = 0 as *mut Application;

/// Execute a command
macro_rules! exec {
    ($cmd:expr) => ({
        unsafe {
            (*application).on_command(&$cmd.to_string());
        }
    })
}
/* } Magic Macros */

/// A command
pub struct Command<'a> {
    pub name: &'a str,
    pub main: Box<Fn(&Vec<String>)>,
}

impl<'a> Command<'a> {
    /// Return the vector of the commands
    // TODO: Use a more efficient collection instead
    pub fn vec() -> Vec<Self> {
        let mut commands: Vec<Self> = Vec::new();
        commands.push(Command {
            name: "echo",
            main: box |args: &Vec<String>| {
                let echo = args.iter()
                    .skip(1)
                    .fold(String::new(), |string, arg| string + " " + arg);
                println!("{}", echo.trim());
            },
        });

        commands.push(Command {
            name: "open",
            main: box |args: &Vec<String>| {
                if let Some(arg) = args.get(1) {
                    File::exec(arg);
                }
            },
        });

        commands.push(Command {
            name: "run",
            main: box |args: &Vec<String>| {
                if let Some(path) = args.get(1) {

                    let mut commands = String::new();
                    if let Some(mut file) = File::open(path) {
                        println!("URL: {:?}", file.path());

                        file.read_to_string(&mut commands);
                    }

                    for command in commands.split('\n') {
                        exec!(command);
                    }
                }
            },
        });

        commands.push(Command {
            name: "send",
            main: box |args: &Vec<String>| {
                if args.len() < 3 {
                    println!("Error: incorrect arguments");
                    println!("Usage: send [url] [data]");
                    return;
                }

                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let string: String = args.iter()
                        .skip(2)
                        .fold(String::new(), |s, arg| s + " " + arg)
                        + "\r\n\r\n";

                    match file.write(string.trim_left().as_bytes()) {
                        Some(size) => println!("Wrote {} bytes", size),
                        None => println!("Failed to write"),
                    }

                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "sleep",
            main: box |args: &Vec<String>| {
                let secs = {
                    match args.get(1) {
                        Some(arg) => arg.to_num() as i64,
                        None => 0,
                    }
                };

                let nanos = {
                    match args.get(2) {
                        Some(arg) => arg.to_num() as i32,
                        None => 0,
                    }
                };

                println!("Sleep: {} {}", secs, nanos);
                let remaining = Duration::new(secs, nanos).sleep();
                println!("Remaining: {} {}", remaining.secs, remaining.nanos);
            },
        });

        commands.push(Command {
            name: "test_ht",
            main: box |args: &Vec<String>| {
                ::redox::hashmap::test();
            },
        });

        commands.push(Command {
            name: "url",
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "url_hex",
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let mut vec: Vec<u8> = Vec::new();
                    match file.read_to_end(&mut vec) {
                        Some(_) => {
                            let mut line = "HEX:".to_string();
                            for byte in vec.iter() {
                                line = line + " " + &format!("{:X}", *byte);
                            }
                            println!("{}", line);
                        }
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "wget",
            main: box |args: &Vec<String>| {
                if let Some(host) = args.get(1) {
                    if let Some(req) = args.get(2) {
                        if let Some(mut con) = File::open(&("tcp://".to_string() + host)) {
                            con.write(("GET ".to_string() + req + " HTTP/1.1").as_bytes());

                            let mut res = Vec::new();
                            con.read_to_end(&mut res);

                            if let Some(mut file) = File::open(&req) {
                                file.write(&res);
                            }
                        }
                    } else {
                        println!("No request given");
                    }
                } else {
                    println!("No url given");
                }
            },
        });

        // Simple command to create a file, in the current directory
        // The file has got the name given as the first argument of the command
        // If the command have no arguments, the command don't create the file
        commands.push(Command {
            name: "cfile",
            main: box |args: &Vec<String>| {
                match args.get(1) {
                    Some(file_name) => {
                        File::create(file_name);
                    }
                    None => {
                        println!("Could not create a file without a name");
                    }
                }
            }
        });

        commands.push(Command {
            name: "pwd",
            main: box |args: &Vec<String>| {
                if let Some(file) = File::open("") {
                    if let Some(path) = file.path() {
                        println!("{}", path);
                    } else {
                        println!("Could not get the path");
                    }
                } else {
                    println!("Could not get the path");
                }
            },
        });

        commands.push(Command {
            name: "cd",
            main: box |args: &Vec<String>| {
                match args.get(1) {
                    Some(path) => {
                        if !change_cwd(&path) {
                            println!("Bad path: {}", path);
                        }
                    }
                    None => println!("No path given")
                }
            },
        });

        let command_list = commands.iter().fold(String::new(), |l , c| l + " " + c.name) + " exit";

        commands.push(Command {
            name: "help",
            main: box move |args: &Vec<String>| {
                println!("Commands:{}", command_list);
            },
         });

        commands
    }
}

/// A (env) variable
pub struct Variable {
    pub name: String,
    pub value: String,
}

pub struct Mode {
    value: bool,
}

/// An application
pub struct Application<'a> {
    commands: Vec<Command<'a>>,
    variables: Vec<Variable>,
    modes: Vec<Mode>,
}

impl<'a> Application<'a> {
    /// Create a new empty application
    pub fn new() -> Self {
        return Application {
            commands: Command::vec(),
            variables: Vec::new(),
            modes: Vec::new(),
        };
    }

    fn on_command(&mut self, command_string: &str) {
        //Comment
        if command_string.starts_with('#') {
            return;
        }

        //Show variables
        if command_string == "$" {
            let variables = self.variables.iter()
                .fold(String::new(),
                      |string, variable| string + "\n" + &variable.name + "=" + &variable.value);
            println!("{}", variables);
            return;
        }

        //Explode into arguments, replace variables
        let mut args: Vec<String> = Vec::<String>::new();
        for arg in command_string.split(' ') {
            if !arg.is_empty() {
                if arg.starts_with('$') {
                    let name = arg[1 .. arg.len()].to_string();
                    for variable in self.variables.iter() {
                        if variable.name == name {
                            args.push(variable.value.clone());
                            break;
                        }
                    }
                } else {
                    args.push(arg.to_string());
                }
            }
        }

        //Execute commands
        if let Some(cmd) = args.get(0) {
            if cmd == "if" {
                let mut value = false;

                if let Some(left) = args.get(1) {
                    if let Some(cmp) = args.get(2) {
                        if let Some(right) = args.get(3) {
                            if cmp == "==" {
                                value = *left == *right;
                            } else if cmp == "!=" {
                                value = *left != *right;
                            } else if cmp == ">" {
                                value = left.to_num_signed() > right.to_num_signed();
                            } else if cmp == ">=" {
                                value = left.to_num_signed() >= right.to_num_signed();
                            } else if cmp == "<" {
                                value = left.to_num_signed() < right.to_num_signed();
                            } else if cmp == "<=" {
                                value = left.to_num_signed() <= right.to_num_signed();
                            } else {
                                println!("Unknown comparison: {}", cmp);
                            }
                        }
                    }
                }

                self.modes.insert(0, Mode { value: value });
                return;
            }

            if cmd == "else" {
                let mut syntax_error = false;
                match self.modes.get_mut(0) {
                    Some(mode) => mode.value = !mode.value,
                    None => syntax_error = true,
                }
                if syntax_error {
                    println!("Syntax error: else found with no previous if");
                }
                return;
            }

            if cmd == "fi" {
                let mut syntax_error = false;
                if !self.modes.is_empty() {
                    self.modes.remove(0);
                } else {
                    syntax_error = true;
                }
                if syntax_error {
                    println!("Syntax error: fi found with no previous if");
                }
                return;
            }

            for mode in self.modes.iter() {
                if !mode.value {
                    return;
                }
            }

            //Set variables
            if let Some(i) = cmd.find('=') {
                let name = cmd[0 .. i].to_string();
                let mut value = cmd[i + 1 .. cmd.len()].to_string();

                if name.is_empty() {
                    return;
                }

                for i in 1..args.len() {
                    if let Some(arg) = args.get(i) {
                        value = value + " " + &arg;
                    }
                }

                if value.is_empty() {
                    let mut remove = -1;
                    for i in 0..self.variables.len() {
                        match self.variables.get(i) {
                            Some(variable) => if variable.name == name {
                                remove = i as isize;
                                break;
                            },
                            None => break,
                        }
                    }

                    if remove >= 0 {
                        self.variables.remove(remove as usize);
                    }
                } else {
                    for variable in self.variables.iter_mut() {
                        if variable.name == name {
                            variable.value = value;
                            return;
                        }
                    }

                    self.variables.push(Variable {
                        name: name,
                        value: value,
                    });
                }
                return;
            }

            //Commands
            for command in self.commands.iter() {
                if &command.name == cmd {
                    (*command.main)(&args);
                    return;
                }
            }

            println!("Unknown command: '{}'", cmd);
        }
    }

    /// Run the application
    pub fn main(&mut self) {
        console_title("Terminal");

        println!("Type help for a command list");
        if let Some(arg) = args().get(1) {
            let command = "run ".to_string() + arg;
            println!("# {}", command);
            self.on_command(&command);
        }

        while let Some(command) = readln!() {
            println!("# {}", command);
            if command == "exit" {
                break;
            } else if !command.is_empty() {
                self.on_command(&command);
            }
        }
    }
}

pub fn main() {
    unsafe {
        let mut app = box Application::new();
        application = app.deref_mut();
        app.main();
    }
}
<|endoftext|>


<commit_before><commit_msg>Add test: Magic Square.<commit_after>//! Magic Square.
//!
//! https://en.wikipedia.org/wiki/Magic_square

extern crate puzzle_solver;

use puzzle_solver::{LinExpr,Puzzle,Solution,Val,VarToken};

fn make_magic_square(n: usize) -> (Puzzle, Vec<Vec<VarToken>>, VarToken) {
    let mut sys = Puzzle::new();
    let digits: Vec<Val> = (1..(n * n + 1) as Val).collect();
    let vars = sys.new_vars_with_candidates_2d(n, n, &digits);

    // Calculate the range of the total (in a dumb way).
    let min = digits.iter().take(n).sum();
    let max = digits.iter().rev().take(n).sum();
    let total = sys.new_var_with_candidates(&(min..max).collect::<Vec<Val>>());

    sys.all_different(vars.iter().flat_map(|it| it));

    for y in 0..n {
        sys.equals(total, vars[y].iter().fold(LinExpr::from(0), |sum, &x| sum + x));
    }

    for x in 0..n {
        sys.equals(total, vars.iter().fold(LinExpr::from(0), |sum, row| sum + row[x]));
    }

    {
        sys.equals(total, (0..n).fold(LinExpr::from(0), |sum, i| sum + vars[i][i]));
        sys.equals(total, (0..n).fold(LinExpr::from(0), |sum, i| sum + vars[i][n - i - 1]));
    }

    // Sum of all digits = sum of all rows (columns) = total * n.
    sys.equals(total * (n as Val), digits.iter().sum::<Val>());

    (sys, vars, total)
}

fn print_magic_square(dict: &Solution, vars: &Vec<Vec<VarToken>>) {
    for row in vars.iter() {
        for &var in row.iter() {
            print!(" {:2}", dict[var]);
        }
        println!();
    }
}

#[test]
fn magicsquare_3x3() {
    let (mut sys, vars, total) = make_magic_square(3);
    let solutions = sys.solve_all();
    assert_eq!(solutions.len(), 8);

    print_magic_square(&solutions[0], &vars);
    for dict in solutions.iter() {
        assert_eq!(dict[total], 15);
    }
    println!("magicsquare_3x3: {} guesses", sys.num_guesses());
}

#[test]
fn magicsquare_4x4() {
    let (mut sys, vars, total) = make_magic_square(4);
    let dict = sys.solve_any().expect("solution");
    print_magic_square(&dict, &vars);
    assert_eq!(dict[total], 34);
}
<|endoftext|>


<commit_before><commit_msg>tests(Hidden Args): adds tests<commit_after><|endoftext|>


<commit_before><commit_msg>Provide a non-compiling example<commit_after>enum Tree {
    Empty,
    Leaf(i32),
    Node(Box<Tree>, Box<Tree>)
}

fn max(a: i32, b: i32) -> i32 {
    if a < b {b} else {a}
}

fn depth(tree: Tree) -> i32 {
    match tree {
        Tree::Empty => 0,
        Tree::Leaf(_) => 1,
        Tree::Node(left, right) => max(depth(*left), depth(*right)) + 1
    }
}

fn main() {
    let tree: Tree = Tree::Node(Box::new(Tree::Empty), Box::new(Tree::Leaf(42)));

    println!("The depth of {} is {}", depth, depth(tree));
}
<|endoftext|>


<commit_before><commit_msg>Added slicing example<commit_after>extern crate gpuarray as ga;

use ga::{Array, Context, RangeArg, Tensor, TensorMode, add_slice};

fn main() {

    let ref ctx = Context::new();

    let a = Array::from_vec(vec![4, 3], vec![2, 3, 4,
                                             6, 7, 8,
                                             10, 11, 12,
                                             14, 15, 16]);
    let at = Tensor::from_array(ctx, &a, TensorMode::Mut);
    let slice: &[RangeArg] = &[RangeArg::from(1..3), RangeArg::from(1)];
    let atv = at.slice(slice);

    let b = Array::from_vec(vec![4, 4], vec![1, 2, 3, 4,
                                             5, 6, 7, 8,
                                             9, 10, 11, 12,
                                             13, 14, 15, 16]);
    let bt = Tensor::from_array(ctx, &b, TensorMode::Mut);
    let slice: &[RangeArg] = &[RangeArg::from(1..3), RangeArg::from(3)];
    let btv = bt.slice(slice);

    let c = Array::from_vec(vec![4, 4], vec![0; 16]);
    let ct = Tensor::from_array(ctx, &c, TensorMode::Mut);
    let slice: &[RangeArg] = &[RangeArg::from(2..4), RangeArg::from(0)];
    let ctv = ct.slice(slice);

    add_slice(ctx, &atv, &btv, &ctv);
    //println!("{:?}", ct.get(ctx));
    assert!(ct.get(ctx).buffer() == &[0, 0, 0, 0,
                                      0, 0, 0, 0,
                                      15, 0, 0, 0,
                                      23, 0, 0, 0]);
}
<|endoftext|>


<commit_before><commit_msg>Add rust quicksort<commit_after>use std::fmt::Debug;

#[allow(dead_code)]
fn quicksort<T: Ord>(arr: &mut [T]) {
    let length = arr.len();
    if length < 2 {
        return;
    }

    let (mut pivot, mut end) = (0, length - 1);
    for _ in 0..length - 1 {
        if arr[pivot] < arr[pivot + 1] {
            arr.swap(pivot + 1, end);
            end -= 1;
        } else {
            arr.swap(pivot, pivot + 1);
            pivot += 1;
        }
    }
    quicksort(&mut arr[..pivot]);
    quicksort(&mut arr[pivot + 1..]);
}

pub fn is_sorted<T: Ord + Debug>(arr: &[T]) ->  bool {
    // This output will be supressed by default
    // Run to see it.
    println!("{:?}", arr);
    for win in arr.windows(2) {
        if win[0] > win[1] {
            return false;
        }
    }
    return true;
}

fn get_test_vecs() -> Vec<Vec<u64>> {
    vec![vec![],
         vec![1],
         vec![1, 2],
         vec![2, 1],
         vec![1, 2, 3],
         vec![2, 1, 3],
         vec![3, 1, 2],
         vec![8, 5, 2, 6, 9, 3],
         vec![2, 3, 5, 6, 8, 9],
         vec![9, 8, 6, 5, 3, 2],
         vec![8, 4, 7, 3, 6, 2, 5, 1],
         vec![8, 1, 7, 2, 6, 3, 5, 4],
         vec![8, 1, 7, 2, 6, 3, 5, 4],
         vec![16, 14, 1, 1, 7, 18, 7, 6, 8, 18, 5],
         vec![19, 18, 14, 15, 3, 9, 8, 2, 2, 20, 11],
         vec![2, 3, 8, 7, 23, 26, 19, 29, 23, 32, 20, 18, 11, 11, 24, 13, 17],
         vec![0, 3, 7, 6],
         vec![6, 4, 4, 5, 11, 10, 10],
         vec![15, 13, 17, 1, 1, 19, 3, 19, 0, 11],
         vec![19, 19, 21, 21, 22, 25, 19, 14, 23, 25, 14, 10, 8, 4, 28, 12, 2, 33],
         vec![8, 1, 0, 5, 3],
         vec![27, 14, 22, 10, 8, 23, 7, 32, 28, 31, 9, 19, 30, 28, 21, 20, 13],
         vec![2, 1, 4, 17, 5, 17, 8, 2, 13, 13]]
}

fn main() {
    let mut tests = get_test_vecs();

    for test in tests.iter_mut() {
        let input = test.as_mut();
        //let result = vec![1, 2, 3];
        quicksort(input);
        assert!(is_sorted(input));
    }
}
<|endoftext|>


<commit_before><commit_msg>[No-auto] lib/entry/datetime: Fix Clippy warnings<commit_after><|endoftext|>


<commit_before><commit_msg>Add problem #43<commit_after><|endoftext|>


<commit_before><commit_msg>added rust kmain source<commit_after>fn kmain() {
    let vid_buffer: *char = 0xb8000 as (*char);
    vid_buff[0] = 'R';
    vid_buffer[1] = 0x07;
}
<|endoftext|>


<commit_before><commit_msg>Add stubs for bot commands<commit_after><|endoftext|>


<commit_before><commit_msg>Add identity test<commit_after>extern crate rgmk;

fn main() {
    let mut args = std::env::args().skip(1);
    let path = args.next().expect("Expected path as argument");
    let root = rgmk::load_from_file(&path).unwrap();
    root.save_to_file(String::from(path) + ".dup").unwrap();
}
<|endoftext|>


<commit_before><commit_msg>Simplify Display impl for Storeid<commit_after><|endoftext|>


<commit_before><commit_msg>Use `STRUCT!()` and `ENUM!()` macros where appropriate<commit_after><|endoftext|>


<commit_before><commit_msg>Fixes for newer rust version<commit_after><|endoftext|>


<commit_before><commit_msg>NonSmallInt.pow()<commit_after><|endoftext|>


<commit_before><commit_msg>add fmt::Display impl for PortMidiError<commit_after><|endoftext|>


<commit_before><commit_msg>added clone of depot_tools if it doesn't exist<commit_after><|endoftext|>


<commit_before><commit_msg>rust-rub work<commit_after><|endoftext|>


<commit_before><commit_msg>Inital Work with If Statement parsing<commit_after><|endoftext|>


<commit_before><commit_msg>string one<commit_after>//string1.rs
fn dump(s: &str) {
    println!("str '{}'", s);
}

fn main() {
    let text = "hello dolly"; //the string slice
    let s = text.to_string(); //now it's an allocated string

    dump(text);
    dump(&s);
}
<|endoftext|>