<commit_before>use std::char;
use std::io;
use std::io::stdio;
use std::str;

#[deriving(Clone)]
enum Token {
  Def,
  Extern,
  Identifier(~str),
  Number(f64),
  Char(char),
  EndOfFile
}

impl Eq for Token {
  fn eq(&self, other: &Token) -> bool {
     match (self, other) {
       (&Def, &Def) => true,
       (&Extern, &Extern) => true,
       (&Identifier(ref val), &Identifier(ref oVal)) => val == oVal,
       (&Number(val), &Number(oVal)) => val == oVal,
       (&Char(val), &Char(oVal)) => val == oVal,
       (&EndOfFile, &EndOfFile) => true,
       (_, _) => false,
     }
  }
}

trait ExprAst {
}

struct NumberExprAst {
  val: f64
}

struct VariableExprAst {
  name: ~str
}

struct BinaryExprAst {
  op: Token,
  lhs: ~ExprAst,
  rhs: ~ExprAst,
}

struct CallExprAst {
  callee: ~str,
  args: ~[~ExprAst]
}

struct PrototypeAst {
  name: ~str,
  argNames: ~[~str]
}

struct FunctionAst {
  proto: ~PrototypeAst,
  body: ~ExprAst
}

impl ExprAst for NumberExprAst {
}
impl ExprAst for VariableExprAst {
}
impl ExprAst for BinaryExprAst {
}
impl ExprAst for CallExprAst {
}

struct Parser {
  tokenInput: Port<Token>,
  currentToken: Token
}

type ParseResult<T> = Result<T, ~str>;

impl Parser {
  fn getNextToken(&mut self) {
    self.currentToken = self.tokenInput.recv();
  }

  fn parseNumberExpr(&mut self) -> ParseResult<~ExprAst> {
    let val = match self.currentToken {
      Number(val) => val,
      _ => return Err(~"token not a number")
    };

    let expr = ~NumberExprAst{val: val};
    self.getNextToken();
    return Ok(expr as ~ExprAst);
  }

  fn parseParenExpr(&mut self) -> ParseResult<~ExprAst> {
    self.getNextToken();
    let expr = match self.parseExpression() {
      Ok(expr) => expr,
      err => return err
    };

    match self.currentToken {
      Char(')') => {},
      _ => return Err(~"expected ')'")
    }
    self.getNextToken();
    return Ok(expr);
  }

  fn parseIdentifierExpr(&mut self) -> ParseResult<~ExprAst> {
    let idName = match self.currentToken {
      Identifier(ref name) => name.clone(),
      _ => return Err(~"token not an identifier")
    };

    self.getNextToken();

    match self.currentToken {
      Char('(') => {},
      _ => return Ok(~VariableExprAst{name: idName} as ~ExprAst)
    }

    self.getNextToken();
    let mut args: ~[~ExprAst] = ~[];
    if self.currentToken != Char(')') {
      loop {
        let arg = self.parseExpression();
        match arg {
          Ok(arg) => args.push(arg),
          err => return err
        }

        if self.currentToken == Char(')') {
          break;
        }

        if self.currentToken != Char(',') {
          return Err(~"Expected ')' or ',' in argument list");
        }

        self.getNextToken();
      }
    }

    self.getNextToken();

    return Ok(~CallExprAst {callee: idName, args: args} as ~ExprAst);
  }

  fn parsePrimary(&mut self) -> ParseResult<~ExprAst> {
    match self.currentToken {
      Identifier(_) => return self.parseIdentifierExpr(),
      Number(_) => return self.parseNumberExpr(),
      Char('(') => return self.parseParenExpr(),
      _ => return Err(~"unknown token when expecting an expression")
    }
  }

  fn parseExpression(&mut self) -> ParseResult<~ExprAst> {
    let lhs: ~ExprAst = match self.parsePrimary() {
      Ok(lhs) => lhs,
      err => return err
    };
    return self.parseBinOpRhs(0, lhs);
  }

  fn parseBinOpRhs(&mut self, exprPrec: int, startLhs: ~ExprAst) -> ParseResult<~ExprAst> {
    let mut lhs = startLhs;
    loop {
      let tokenPrec = self.getTokenPrecedence();
      if tokenPrec < exprPrec {
        return Ok(lhs);
      }

      let binOp = self.currentToken.clone();
      self.getNextToken();

      let mut rhs = match self.parsePrimary() {
        Ok(rhs) => rhs,
        err => return err
      };

      let nextPrec = self.getTokenPrecedence();

      if tokenPrec < nextPrec {
        rhs = match self.parseBinOpRhs(tokenPrec+1, rhs) {
          Ok(rhs) => rhs,
          err => return err
        };
      }
      lhs = ~BinaryExprAst {op: binOp, lhs: lhs, rhs: rhs} as ~ExprAst;
    }
  }

  fn parsePrototype(&mut self) -> ParseResult<~PrototypeAst> { // possibly need sep. of Prototype and Expr
    let fnName: ~str = match self.currentToken {
      Identifier(ref name) => name.clone(),
      _ => return Err(~"Expected function name in prototype")
    };

    self.getNextToken();
    if self.currentToken != Char('(') {
      println!("had a {:?}", self.currentToken);
      return Err(~"Expected '(' in prototype");
    }

    let mut argNames: ~[~str] = ~[];
    loop {
      self.getNextToken();
      match self.currentToken {
        Identifier(ref name) => argNames.push(name.clone()),
        _ => break
      }
    }
    if self.currentToken != Char(')') {
      return Err(~"Expected ')' in prototype");
    }

    self.getNextToken();

    return Ok(~PrototypeAst {name: fnName, argNames: argNames});
  }

  fn parseDefinition(&mut self) -> ParseResult<~FunctionAst> {
    self.getNextToken();
    let proto = match self.parsePrototype() {
      Ok(proto) => proto,
      Err(err) => return Err(err)
    };
    let expr = match self.parseExpression() {
      Ok(expr) => expr,
      Err(err) => return Err(err)
    };
    return Ok(~FunctionAst{proto: proto, body: expr});
  }

  fn parseExtern(&mut self) -> ParseResult<~PrototypeAst> {
    self.getNextToken(); // consume "expr"
    return self.parsePrototype();
  }

  fn parseTopLevelExpr(&mut self) -> ParseResult<~FunctionAst> {
    let expr = match self.parseExpression() {
      Ok(expr) => expr,
      Err(err) => return Err(err)
    };

    let proto = ~PrototypeAst {name: ~"", argNames: ~[]};
    return Ok(~FunctionAst{proto: proto, body: expr});
  }

  fn getTokenPrecedence(&mut self) -> int {
    match self.currentToken {
      Char(t) => match t {
        '<' => return 10,
        '+' => return 20,
        '-' => return 20,
        '*' => return 40,
        '/' => return 40,
        _   => return -1
      },
      _ => return -1
    }
  }

  fn run(&mut self) {
    print!("ready> ");
    stdio::flush();
    self.getNextToken();

    loop {
      match self.currentToken {
        Def => self.handleDefinition(),
        Extern => self.handleExtern(),
        Char(';') => {
          self.getNextToken();
          continue;
        },
        _ => self.handleTopLevelExpression()
      }

      print!("ready> ");
      stdio::flush();
    }
  }

  fn handleDefinition(&mut self) {
    let def = self.parseDefinition();
    match def {
      Ok(def) => println!("Parsed a function definition"),
      Err(why) => {
        println!("Error: {}", why);
        self.getNextToken();
      }
    }
  }

  fn handleExtern(&mut self) {
    let ext = self.parseExtern();
    match ext {
      Ok(ext) => println!("Parsed an extern"),
      Err(why) => {
        println!("Error parsing extern: {}", why);
        self.getNextToken();
      }
    }
  }

  fn handleTopLevelExpression(&mut self) {
    let tle = self.parseTopLevelExpr();
    match tle {
      Ok(tle) => println!("Parsed a top level expr"),
      Err(why) => {
        println!("Error parsing tle: {}", why);
        self.getNextToken();
      }
    }
  }
}

fn readTokens(tokenChan: Chan<Token>) -> proc() {
  return proc() {
    let mut reader = io::stdin();
    let mut lastChr = ' ';

    loop {
      while lastChr == ' ' || lastChr == '\r' || lastChr == '\n' || lastChr == '\t' {
        lastChr = match reader.read_char() {
          Ok(chr) => chr,
          Err(_) => break
        };
      }

      if char::is_alphabetic(lastChr) { // identifier [a-zA-Z][a-zA-Z0-9]*
        let mut identifierStr : ~[char] = ~[lastChr];
        loop {
          match reader.read_char() {
            Ok(chr) => {
              if char::is_alphabetic(chr) {
                identifierStr.push(chr);
              } else {
                lastChr = chr;
                break;
              }
            },
            Err(_) => {
              tokenChan.send(EndOfFile);
              return;
            }
          }
        }
        match str::from_chars(identifierStr) {
          ~"def" => {
            tokenChan.send(Def);
            continue;
          },
          ~"extern" => {
            tokenChan.send(Extern);
            continue;
          },
          id => {
            tokenChan.send(Identifier(id));
            continue;
          }
        }
      }

      if char::is_digit(lastChr) || lastChr == '.' { // number: [0-9.]+
        let mut numStr = ~[lastChr];
        loop {
          match reader.read_char() {
            Ok(chr) => {
              if char::is_digit(chr) || chr == '.' {
                numStr.push(chr);
              } else {
                lastChr = chr;
                break;
              }
            },
            Err(_) => {
              tokenChan.send(EndOfFile);
              return;
            }
          }
        }
        tokenChan.send(Number(match from_str::<f64>(str::from_chars(numStr)) {
          Some(val) => val,
          None => {
            println!("Malformed number");
            continue;
          }
        }));
        continue;
      }

      if lastChr == '#' {
        loop {
          match reader.read_char() {
            Ok(chr) => {
              if chr == '\r' || chr == '\n' {
                lastChr = ' ';
                break;
              }
            },
            Err(_) => {
              tokenChan.send(EndOfFile);
              return;
            }
          }
        }
        continue;
      }

      tokenChan.send(Char(lastChr));
      // consume lastChr
      lastChr = ' ';
    }
    tokenChan.send(EndOfFile);
  };
}

fn main() {
  let (tokenPort, tokenChan) = Chan::new();

  spawn(readTokens(tokenChan));
  let mut parser = Parser {tokenInput: tokenPort, currentToken: Char(' ')};
  parser.run();
}
<commit_msg>Add initial codegen implementations<commit_after>extern crate collections;
extern crate rustc;

use collections::HashMap;

use rustc::lib::llvm::{ValueRef, ModuleRef, TypeRef, ContextRef, BuilderRef, RealULT, False};
use rustc::lib::llvm::llvm;

use std::char;
use std::io;
use std::io::stdio;
use std::str;
use std::vec;
use std::libc::{c_uint};

#[deriving(Clone)]
enum Token {
  Def,
  Extern,
  Identifier(~str),
  Number(f64),
  Char(char),
  EndOfFile
}

impl Eq for Token {
  fn eq(&self, other: &Token) -> bool {
     match (self, other) {
       (&Def, &Def) => true,
       (&Extern, &Extern) => true,
       (&Identifier(ref val), &Identifier(ref oVal)) => val == oVal,
       (&Number(val), &Number(oVal)) => val == oVal,
       (&Char(val), &Char(oVal)) => val == oVal,
       (&EndOfFile, &EndOfFile) => true,
       (_, _) => false,
     }
  }
}

trait ExprAst {
  unsafe fn codegen(&self, &mut Parser) -> ValueRef;
}

struct NumberExprAst {
  val: f64
}

struct VariableExprAst {
  name: ~str
}

struct BinaryExprAst {
  op: Token,
  lhs: ~ExprAst,
  rhs: ~ExprAst,
}

struct CallExprAst {
  callee: ~str,
  args: ~[~ExprAst]
}

struct PrototypeAst {
  name: ~str,
  argNames: ~[~str]
}

struct FunctionAst {
  proto: ~PrototypeAst,
  body: ~ExprAst
}

impl ExprAst for NumberExprAst {
  unsafe fn codegen(&self, parser: &mut Parser) -> ValueRef {
    let ty = llvm::LLVMDoubleTypeInContext(parser.contextRef);
    return llvm::LLVMConstReal(ty, self.val);
  }
}

impl ExprAst for VariableExprAst {
  unsafe fn codegen(&self, parser: &mut Parser) -> ValueRef {
    return match parser.namedValues.find(&self.name) {
      Some(v) => *v,
      None => fail!("Unknown variable name")
    };
  }
}
impl ExprAst for BinaryExprAst {
  unsafe fn codegen(&self, parser: &mut Parser) -> ValueRef {
    let lhsValue = self.lhs.codegen(parser);
    let rhsValue = self.rhs.codegen(parser);
    match self.op {
      Char('+') => return "addtmp".with_c_str(|name| llvm::LLVMBuildFAdd(parser.builderRef, lhsValue, rhsValue, name)),
      Char('-') => return "subtmp".with_c_str(|name| llvm::LLVMBuildFSub(parser.builderRef, lhsValue, rhsValue, name)),
      Char('*') => return "multmp".with_c_str(|name| llvm::LLVMBuildFMul(parser.builderRef, lhsValue, rhsValue, name)),
      Char('<') => {

        let cmpValue = "cmptmp".with_c_str(|name| llvm::LLVMBuildFCmp(parser.builderRef, RealULT as c_uint, lhsValue, rhsValue, name));
        let ty = llvm::LLVMDoubleTypeInContext(parser.contextRef);
        return "booltmp".with_c_str(|name| llvm::LLVMBuildUIToFP(parser.builderRef, cmpValue, ty, name));
      }
      _ => {
        fail!("llvm code gen failed, invalid binary operation");
      }
    }

  }
}

impl ExprAst for CallExprAst {
  unsafe fn codegen(&self, parser: &mut Parser) -> ValueRef {
    let funType : TypeRef = parser.getDoubleFunType(self.args.len());
    let calleeF = self.callee.with_c_str(|name| llvm::LLVMGetOrInsertFunction(parser.moduleRef, name, funType));

    // TODO check arg size
    let mut argsV : ~[ValueRef] = ~[];
    for arg in self.args.iter() {
      argsV.push(arg.codegen(parser));
    }

    return "calltmp".with_c_str(|name| llvm::LLVMBuildCall(parser.builderRef, calleeF, argsV.as_ptr(), argsV.len() as c_uint, name));
  }
}

impl PrototypeAst {
  unsafe fn codegen(&self, parser: &mut Parser) -> ValueRef {
    let funType = parser.getDoubleFunType(self.argNames.len());
    let fun = self.name.with_c_str(|name| llvm::LLVMGetOrInsertFunction(parser.moduleRef, name, funType));
    if llvm::LLVMCountBasicBlocks(fun) != 0 {
      fail!("Redefinition of function");
    }
    let nArgs = llvm::LLVMCountParams(fun) as uint;
    if nArgs != 0 && nArgs != self.argNames.len() {
      fail!("Redefinition of function with different argument count");
    }

    for (i, argName) in self.argNames.iter().enumerate() {
      let llarg = llvm::LLVMGetParam(fun, i as c_uint);
      argName.with_c_str(|name| llvm::LLVMSetValueName(llarg, name));
    }

    return fun;
  }
}

struct Parser {
  tokenInput: Receiver<Token>,
  currentToken: Token,
  moduleRef: ModuleRef,
  builderRef: BuilderRef,
  contextRef: ContextRef,
  namedValues: HashMap<~str, ValueRef>
}

type ParseResult<T> = Result<T, ~str>;

impl Parser {
  fn new(tokenInput: Receiver<Token>) -> Parser {
    let llcx = unsafe { llvm::LLVMContextCreate() };
    let llmod = unsafe {
      "kaleidoscope".with_c_str(|name| {
        llvm::LLVMModuleCreateWithNameInContext(name, llcx)
      })
    };
    let llbuilder = unsafe {
      llvm::LLVMCreateBuilderInContext(llcx)
    };
    return Parser {
      tokenInput: tokenInput,
      currentToken: Char(' '),
      moduleRef: llmod,
      builderRef: llbuilder,
      contextRef: llcx,
      namedValues: HashMap::new()
    };
  }

  unsafe fn getDoubleFunType(&mut self, argc: uint) -> TypeRef {
    let ty = llvm::LLVMDoubleTypeInContext(self.contextRef);
    let doubles : ~[TypeRef] = vec::from_fn(argc, |_| ty);
    return llvm::LLVMFunctionType(ty, doubles.as_ptr(), argc as c_uint, False);
  }

  fn getNextToken(&mut self) {
    self.currentToken = self.tokenInput.recv();
  }

  fn parseNumberExpr(&mut self) -> ParseResult<~ExprAst> {
    let val = match self.currentToken {
      Number(val) => val,
      _ => return Err(~"token not a number")
    };

    let expr = ~NumberExprAst{val: val};
    self.getNextToken();
    return Ok(expr as ~ExprAst);
  }

  fn parseParenExpr(&mut self) -> ParseResult<~ExprAst> {
    self.getNextToken();
    let expr = match self.parseExpression() {
      Ok(expr) => expr,
      err => return err
    };

    match self.currentToken {
      Char(')') => {},
      _ => return Err(~"expected ')'")
    }
    self.getNextToken();
    return Ok(expr);
  }

  fn parseIdentifierExpr(&mut self) -> ParseResult<~ExprAst> {
    let idName = match self.currentToken {
      Identifier(ref name) => name.clone(),
      _ => return Err(~"token not an identifier")
    };

    self.getNextToken();

    match self.currentToken {
      Char('(') => {},
      _ => return Ok(~VariableExprAst{name: idName} as ~ExprAst)
    }

    self.getNextToken();
    let mut args: ~[~ExprAst] = ~[];
    if self.currentToken != Char(')') {
      loop {
        let arg = self.parseExpression();
        match arg {
          Ok(arg) => args.push(arg),
          err => return err
        }

        if self.currentToken == Char(')') {
          break;
        }

        if self.currentToken != Char(',') {
          return Err(~"Expected ')' or ',' in argument list");
        }

        self.getNextToken();
      }
    }

    self.getNextToken();

    return Ok(~CallExprAst {callee: idName, args: args} as ~ExprAst);
  }

  fn parsePrimary(&mut self) -> ParseResult<~ExprAst> {
    match self.currentToken {
      Identifier(_) => return self.parseIdentifierExpr(),
      Number(_) => return self.parseNumberExpr(),
      Char('(') => return self.parseParenExpr(),
      _ => return Err(~"unknown token when expecting an expression")
    }
  }

  fn parseExpression(&mut self) -> ParseResult<~ExprAst> {
    let lhs: ~ExprAst = match self.parsePrimary() {
      Ok(lhs) => lhs,
      err => return err
    };
    return self.parseBinOpRhs(0, lhs);
  }

  fn parseBinOpRhs(&mut self, exprPrec: int, startLhs: ~ExprAst) -> ParseResult<~ExprAst> {
    let mut lhs = startLhs;
    loop {
      let tokenPrec = self.getTokenPrecedence();
      if tokenPrec < exprPrec {
        return Ok(lhs);
      }

      let binOp = self.currentToken.clone();
      self.getNextToken();

      let mut rhs = match self.parsePrimary() {
        Ok(rhs) => rhs,
        err => return err
      };

      let nextPrec = self.getTokenPrecedence();

      if tokenPrec < nextPrec {
        rhs = match self.parseBinOpRhs(tokenPrec+1, rhs) {
          Ok(rhs) => rhs,
          err => return err
        };
      }
      lhs = ~BinaryExprAst {op: binOp, lhs: lhs, rhs: rhs} as ~ExprAst;
    }
  }

  fn parsePrototype(&mut self) -> ParseResult<~PrototypeAst> { // possibly need sep. of Prototype and Expr
    let fnName: ~str = match self.currentToken {
      Identifier(ref name) => name.clone(),
      _ => return Err(~"Expected function name in prototype")
    };

    self.getNextToken();
    if self.currentToken != Char('(') {
      println!("had a {:?}", self.currentToken);
      return Err(~"Expected '(' in prototype");
    }

    let mut argNames: ~[~str] = ~[];
    loop {
      self.getNextToken();
      match self.currentToken {
        Identifier(ref name) => argNames.push(name.clone()),
        _ => break
      }
    }
    if self.currentToken != Char(')') {
      return Err(~"Expected ')' in prototype");
    }

    self.getNextToken();

    return Ok(~PrototypeAst {name: fnName, argNames: argNames});
  }

  fn parseDefinition(&mut self) -> ParseResult<~FunctionAst> {
    self.getNextToken();
    let proto = match self.parsePrototype() {
      Ok(proto) => proto,
      Err(err) => return Err(err)
    };
    let expr = match self.parseExpression() {
      Ok(expr) => expr,
      Err(err) => return Err(err)
    };
    return Ok(~FunctionAst{proto: proto, body: expr});
  }

  fn parseExtern(&mut self) -> ParseResult<~PrototypeAst> {
    self.getNextToken(); // consume "expr"
    return self.parsePrototype();
  }

  fn parseTopLevelExpr(&mut self) -> ParseResult<~FunctionAst> {
    let expr = match self.parseExpression() {
      Ok(expr) => expr,
      Err(err) => return Err(err)
    };

    let proto = ~PrototypeAst {name: ~"", argNames: ~[]};
    return Ok(~FunctionAst{proto: proto, body: expr});
  }

  fn getTokenPrecedence(&mut self) -> int {
    match self.currentToken {
      Char(t) => match t {
        '<' => return 10,
        '+' => return 20,
        '-' => return 20,
        '*' => return 40,
        '/' => return 40,
        _   => return -1
      },
      _ => return -1
    }
  }

  fn run(&mut self) {
    print!("ready> ");
    stdio::flush();
    self.getNextToken();

    loop {
      match self.currentToken {
        Def => self.handleDefinition(),
        Extern => self.handleExtern(),
        Char(';') => {
          self.getNextToken();
          continue;
        },
        _ => self.handleTopLevelExpression()
      }

      print!("ready> ");
      stdio::flush();
    }
  }

  fn handleDefinition(&mut self) {
    let def = self.parseDefinition();
    match def {
      Ok(def) => println!("Parsed a function definition"),
      Err(why) => {
        println!("Error: {}", why);
        self.getNextToken();
      }
    }
  }

  fn handleExtern(&mut self) {
    let ext = self.parseExtern();
    match ext {
      Ok(ext) => println!("Parsed an extern"),
      Err(why) => {
        println!("Error parsing extern: {}", why);
        self.getNextToken();
      }
    }
  }

  fn handleTopLevelExpression(&mut self) {
    let tle = self.parseTopLevelExpr();
    match tle {
      Ok(tle) => println!("Parsed a top level expr"),
      Err(why) => {
        println!("Error parsing tle: {}", why);
        self.getNextToken();
      }
    }
  }
}

fn readTokens(tokenSender: Sender<Token>) -> proc() {
  return proc() {
    let mut reader = io::stdin();
    let mut lastChr = ' ';

    loop {
      while lastChr == ' ' || lastChr == '\r' || lastChr == '\n' || lastChr == '\t' {
        lastChr = match reader.read_char() {
          Ok(chr) => chr,
          Err(_) => break
        };
      }

      if char::is_alphabetic(lastChr) { // identifier [a-zA-Z][a-zA-Z0-9]*
        let mut identifierStr : ~[char] = ~[lastChr];
        loop {
          match reader.read_char() {
            Ok(chr) => {
              if char::is_alphabetic(chr) {
                identifierStr.push(chr);
              } else {
                lastChr = chr;
                break;
              }
            },
            Err(_) => {
              tokenSender.send(EndOfFile);
              return;
            }
          }
        }
        let identifier = str::from_chars(identifierStr);
        if identifier == ~"def" {
          tokenSender.send(Def);
        } else if identifier == ~"extern" {
          tokenSender.send(Extern);
        } else {
          tokenSender.send(Identifier(identifier));
        }
        continue;
      }

      if char::is_digit(lastChr) || lastChr == '.' { // number: [0-9.]+
        let mut numStr = ~[lastChr];
        loop {
          match reader.read_char() {
            Ok(chr) => {
              if char::is_digit(chr) || chr == '.' {
                numStr.push(chr);
              } else {
                lastChr = chr;
                break;
              }
            },
            Err(_) => {
              tokenSender.send(EndOfFile);
              return;
            }
          }
        }
        tokenSender.send(Number(match from_str::<f64>(str::from_chars(numStr)) {
          Some(val) => val,
          None => {
            println!("Malformed number");
            continue;
          }
        }));
        continue;
      }

      if lastChr == '#' {
        loop {
          match reader.read_char() {
            Ok(chr) => {
              if chr == '\r' || chr == '\n' {
                lastChr = ' ';
                break;
              }
            },
            Err(_) => {
              tokenSender.send(EndOfFile);
              return;
            }
          }
        }
        continue;
      }

      tokenSender.send(Char(lastChr));
      // consume lastChr
      lastChr = ' ';
    }
  };
}

fn main() {
  let (tokenSender, tokenReceiver) = channel();

  spawn(readTokens(tokenSender));
  let mut parser = Parser::new(tokenReceiver);
  parser.run();
}
<|endoftext|>


<commit_before>static GRID_SIZE: uint = 10;

enum CellValue {
  alive, dead
}

struct Cell {
  cv: CellValue
}  // struct Cell

impl Cell {
  /*
    This fn prints to std::io indicating whether the cell is alive or dead.
  */
  fn print(&self) {
    match self.cv {
      alive => print("O"),
      dead  => print("X")
    }
  }
  /*
    Standard ctor, returns an 'alive' cell.
  */
  fn new() -> Cell {
    Cell { cv: alive }
  }

  /*
    This fn flips the value from dead => alive, or visa versa.
  */
  fn flip(&mut self) -> () {
    self.cv = match self.cv { alive => dead, dead => alive };
  }  // fn flip
}  // impl Cell

struct Height(uint);
struct Width(uint);

struct Grid {
  priv inner: [ [Cell, .. GRID_SIZE], ..GRID_SIZE],
}

impl Grid {
  /*
    Invokes print on each cell, separating rows with newlines.
  */
  fn print(&self) {
    let grid = &self.inner;
    for outer in grid.iter() {
      for inner in outer.iter() {
        inner.print();
      }
      print("\n");
    }
  }  // fn print

  /*
    This function returns a GRID_SIZE by GRID_SIZE 2D array (GRID)
    initially all set to dead.
  */
  fn new() -> Grid {
    Grid { inner: [[ Cell::new(), .. GRID_SIZE], .. GRID_SIZE] }
  }  // fn new
  /*
    This fn flips the value from dead => alive, or visa versa.
  */
  fn flip_cell(& mut self, w: Width, h: Height) {
    println(fmt!("w %u h %u", *w, *h));
    assert!(*w < GRID_SIZE && *h < GRID_SIZE);
    assert!(*h < GRID_SIZE);
    // Delegate how to flip to the cell itself.
    self.inner[*w][*h].flip();
  }

  /*
    Returns a reference to the cell just to the right
    of the cell with a width 'w'.
  */
  fn get_right_neighbor(&self, w: Width, h: Height) -> &Cell {
    // this SHOULD return a ref to itself, no?
    &self.inner[0][0]
  }  // fn get_right_neighbor

  /*
    This fn returns the number of dead neighbors for a cell within the grid.
  */
  fn count_dead_neighbors(&self, w: Width, h: Height) -> uint {
    let above_neighbor: &Cell = self.get_right_neighbor(w, h);
    0
  }  // fn count_dead_neighbors
}

fn main () {
  println("hello");
  let mut gr: Grid = Grid::new();
  gr.print();
  gr.flip_cell(Width(0), Height(0));
  gr.print();
}
<commit_msg>Worked some more today.<commit_after>static GRID_SIZE: uint = 10;
static GRID_MAX_INDEX: uint = GRID_SIZE - 1;

#[deriving(Eq)]
enum CellValue {
  alive, dead
}

struct Cell {
  cv: CellValue,
  row: Row,
  column: Column
}  // struct Cell

impl Cell {
  /*
    This fn prints to std::io indicating whether the cell is alive or dead.
  */
  fn print(&self) {
    //print(fmt!("%u", *self.row));
    match self.cv {
      alive => print("O"),
      dead  => print("X")
    }
  }
  /*
    Standard ctor, returns an 'alive' cell.
  */
  fn new(row_param: Row, col_param: Column) -> Cell {
    Cell { cv: alive, row: row_param, column: col_param }
  }

  /*
    This fn flips the value from dead => alive, or visa versa.
  */
  fn flip(&mut self) -> () {
    self.cv = match self.cv { alive => dead, dead => alive };
  }  // fn flip
}  // impl Cell

struct Row(uint);
struct Column(uint);

struct Grid {
  priv inner: [ [Cell, .. GRID_SIZE], ..GRID_SIZE],
}

impl Grid {

  /*
    Invokes an arbitrary fn on each cell.
  */
  fn each_cell(&self, function: &fn()) {
    let grid = &self.inner;
    for outer in grid.iter() {
      for _ in outer.iter() {
        function();
      }
    }
  }  // fn each
  /*
    Invokes print on each cell, separating rows with newlines.
  */
  fn print(&self) {
    let grid = &self.inner;
    for outer in grid.iter() {
      for inner in outer.iter() {
        inner.print();
      }
      print("\n");
    }
  }  // fn print

  /*
    This function returns a GRID_MAX_INDEX by GRID_MAX_INDEX 2D array (GRID)
    initially all set to dead.
  */
  fn new() -> Grid {
    // TODO: Is this a good way to indent ??
    let mut result = Grid {
        inner: [[ Cell::new(Row(0), Column(0)), .. GRID_SIZE], .. GRID_SIZE]
    };

    // TODO: Do I need explicit for loops? Rather use an algorithm ..
    for o in range(0, GRID_MAX_INDEX) {
      for i in range(0, GRID_MAX_INDEX) {
        let cell = Cell::new(Row(i), Column(o));
        result.inner[o][i] = cell;
      }  // 'for i' loop
    } // 'for o' loop
    result
  }  // fn new
  /*
    This fn flips the value from dead => alive, or visa versa.
  */
  fn flip_cell(& mut self, col: Column, row: Row) {
    println(fmt!("w %u h %u", *col, *row));
    assert!(*col < GRID_MAX_INDEX && *row < GRID_MAX_INDEX);
    assert!(*row < GRID_MAX_INDEX);
    // Delegate how to flip to the cell itself.
    self.inner[*col][*row].flip();
  }  // fn flip_cell

  /*
    Returns a reference to the cell just to the right
    of the cell with a column 'w'.
    NOTE: The 'r  is a lifetime identifier. Here, 'r is telling me that the returned Cell
    borrowed pointer is the same lifetime as the 'self' parameter.
  */
  fn get_right_neighbor<'r>(&'r self, col: Column, row: Row) -> &'r Cell {
    match *col {
      GRID_MAX_INDEX => &self.inner[*row][0],  // Wrap around back to left side.
      _         => &self.inner[*row][*col + 1]
    }
  }  // fn get_right_neighbor

  fn get_left_neighbor<'r>(&'r self, col: Column, row: Row) -> &'r Cell {
    match *col {
      0 => &self.inner[*row][GRID_MAX_INDEX], // Wrap around to right side.
      _ => &self.inner[*row][*col - 1]
    }
  }  // fn get_left_neighbor

  fn get_above_neighbor<'r>(&'r self, col: Column, row: Row) -> &'r Cell {
    match *row {
      0 => &self.inner[GRID_MAX_INDEX][*col], // Wrap around to bottom side.
      _ => &self.inner[*row - 1][*col]
    }
  }  // fn get_above_neighbor

  fn get_below_neighbor<'r>(&'r self, col: Column, row: Row) -> &'r Cell {
    match *row {
      GRID_MAX_INDEX => &self.inner[0][*col], // Wrap around to top side.
      _         => &self.inner[*row + 1][*col]
    }
  } // fn get_below_neighbor

  fn get_upper_left_neighbor<'r>(&'r self, col: Column, row: Row) -> &'r Cell {
    let left_neighbor = self.get_left_neighbor(col, row);
    // retun the above neighbor of the left_neighbor
    return self.get_above_neighbor(left_neighbor.column, left_neighbor.row);
  }  // fn get_upper_left_neighbor

  fn get_upper_right_neighbor<'r>(&'r self, col: Column, row: Row) -> &'r Cell {
    let right_neighbor = self.get_right_neighbor(col, row);
    return self.get_above_neighbor(right_neighbor.column, right_neighbor.row);
  }  // fn get_upper_right_neighbor

  fn get_below_right_neighbor<'r>(&'r self, col: Column, row: Row) -> &'r Cell {
    let right_neighbor = self.get_right_neighbor(col, row);
    return self.get_below_neighbor(right_neighbor.column, right_neighbor.row);
  }  // fn get_below_right_neighbor

  fn get_below_left_neighbor<'r>(&'r self, col: Column, row: Row) -> &'r Cell {
    let left_neighbor = self.get_left_neighbor(col, row);
    return self.get_below_neighbor(left_neighbor.column, left_neighbor.row);
  }  // fn get_below_left_neighbor

  /*
    This fn returns the number of dead neighbors for a cell within the grid.
  */
  fn count_dead_neighbors(&self, col: Column, row: Row) -> uint {
    let check_cell = |cell: &Cell| -> uint {
      match cell.cv {
        alive => 1,
        dead => 0
      }
    };

    let arr = [
        check_cell(self.get_left_neighbor(col, row)),
        check_cell(self.get_right_neighbor(col, row)),
        check_cell(self.get_above_neighbor(col, row)),
        check_cell(self.get_below_neighbor(col, row)),
        check_cell(self.get_upper_left_neighbor(col, row)),
        check_cell(self.get_upper_right_neighbor(col, row)),
        check_cell(self.get_below_right_neighbor(col, row)),
        check_cell(self.get_below_left_neighbor(col, row)),
    ];
    let accumulator = |v: &[uint]| -> uint {
      let mut aggregate = 0u;
      for item in v.iter() {
        aggregate += *item;
      }
      aggregate
    };

    return accumulator(arr);
  }  // fn count_dead_neighbors
}

fn main () {
  let mut gr: Grid = Grid::new();
  gr.flip_cell(Column(0), Row(0));

  for outer in gr.inner.iter() {
    for &inner in outer.iter() {
      let dead_neighbor_count = gr.count_dead_neighbors(Column(0), Row(0));
      if (dead_neighbor_count < 2) {
        inner.flip();
      }
    }
  }

  let dead_count = gr.count_dead_neighbors(Column(0), Row(0));
  print(fmt!("%u", dead_count));
}
<|endoftext|>


<commit_before>// AsRef and AsMut allow for cheap reference-to-reference conversions.
// Read more about them at https://doc.rust-lang.org/std/convert/trait.AsRef.html
// and https://doc.rust-lang.org/std/convert/trait.AsMut.html, respectively.

// I AM NOT DONE
// Obtain the number of bytes (not characters) in the given argument
// Add the AsRef trait appropriately as a trait bound
fn byte_counter<T>(arg: T) -> usize {
    arg.as_ref().as_bytes().len()
}

// Obtain the number of characters (not bytes) in the given argument
// Add the AsRef trait appropriately as a trait bound
fn char_counter<T>(arg: T) -> usize {
    arg.as_ref().chars().count()
}

fn main() {
    let s = "Café au lait";
    println!("{}", char_counter(s));
    println!("{}", byte_counter(s));
}

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

    #[test]
    fn different_counts() {
        let s = "Café au lait";
        assert_ne!(char_counter(s), byte_counter(s));
    }

    #[test]
    fn same_counts() {
        let s = "Cafe au lait";
        assert_eq!(char_counter(s), byte_counter(s));
    }
}
<commit_msg>Added  example to show the AsRef working<commit_after>// AsRef and AsMut allow for cheap reference-to-reference conversions.
// Read more about them at https://doc.rust-lang.org/std/convert/trait.AsRef.html
// and https://doc.rust-lang.org/std/convert/trait.AsMut.html, respectively.

// I AM NOT DONE
// Obtain the number of bytes (not characters) in the given argument
// Add the AsRef trait appropriately as a trait bound
fn byte_counter<T>(arg: T) -> usize {
    arg.as_ref().as_bytes().len()
}

// Obtain the number of characters (not bytes) in the given argument
// Add the AsRef trait appropriately as a trait bound
fn char_counter<T>(arg: T) -> usize {
    arg.as_ref().chars().count()
}

fn main() {
    let s = "Café au lait";
    println!("{}", char_counter(s));
    println!("{}", byte_counter(s));
}

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

    #[test]
    fn different_counts() {
        let s = "Café au lait";
        assert_ne!(char_counter(s), byte_counter(s));
    }

    #[test]
    fn same_counts() {
        let s = "Cafe au lait";
        assert_eq!(char_counter(s), byte_counter(s));
    }

    #[test]
    fn different_counts_using_string() {
        let s = String::from("Café au lait");
        assert_ne!(char_counter(s.clone()), byte_counter(s));
    }

    #[test]
    fn same_counts_using_string() {
        let s = String::from("Cafe au lait");
        assert_eq!(char_counter(s.clone()), byte_counter(s));
    }
}
<|endoftext|>


<commit_before>extern crate chrono;
use chrono::{DateTime, Duration};

pub fn after(d: DateTime<UTC>) -> DateTime<UTC> {
    d + Duration::seconds(1e9 as i64)
}
<commit_msg>make it actually compile<commit_after>extern crate chrono;
use chrono::{DateTime, Duration, UTC};

pub fn after(d: DateTime<UTC>) -> DateTime<UTC> {
    d + Duration::seconds(1_000_000_000)
}
<|endoftext|>


<commit_before>use std::io;

use buffoon::{Serialize, Deserialize, OutputStream, InputStream};
use rustc_serialize::base64::{self, ToBase64};
use serde_json::builder::ObjectBuilder;

use algorithm::{EncryptionAlgorithm, SignatureAlgorithm};
use error::{Error, Result};
use proto::ToProto;
use objecthash::{self, ObjectHash, ObjectHasher};

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum Type {
    SignatureKeyPair(SignatureAlgorithm),
}

#[derive(Debug, Eq, PartialEq)]
pub struct CredentialObject {
    keyid: Vec<u8>,
    credential_type: Type,
    sealing_alg: EncryptionAlgorithm,
    encrypted_value: Vec<u8>,
    public_key: Option<Vec<u8>>,
    not_before: Option<u64>,
    not_after: Option<u64>,
    description: Option<String>,
}

impl Type {
    fn protobuf_id(&self) -> u32 {
        match *self {
            Type::SignatureKeyPair(_) => 1,
        }
    }

    fn protobuf_alg(&self) -> String {
        match *self {
            // TODO: factor this into SignatureAlgorithm
            Type::SignatureKeyPair(SignatureAlgorithm::Ed25519) => String::from("Ed25519"),
        }
    }

    // TODO: actually support more algorithms
    fn from_id_and_alg(credential_id: Option<u32>, credential_alg: Option<String>) -> Result<Type> {
        if credential_id != Some(1) {
            return Err(Error::Parse);
        }

        if credential_alg != Some(String::from("Ed25519")) {
            return Err(Error::Parse);
        }

        Ok(Type::SignatureKeyPair(SignatureAlgorithm::Ed25519))
    }
}

impl ToString for Type {
    fn to_string(&self) -> String {
        match *self {
            Type::SignatureKeyPair(_) => String::from("SIGNATURE_KEY_PAIR"),
        }
    }
}

impl CredentialObject {
    pub fn signature_keypair(sealing_alg: EncryptionAlgorithm,
                             signature_alg: SignatureAlgorithm,
                             sealed_keypair: &[u8],
                             public_key: &[u8],
                             not_before: u64,
                             not_after: u64,
                             description: Option<String>)
                             -> CredentialObject {
        // Ed25519 is the only signature algorithm we presently support
        assert!(signature_alg == SignatureAlgorithm::Ed25519);

        CredentialObject {
            keyid: Vec::from(public_key),
            credential_type: Type::SignatureKeyPair(SignatureAlgorithm::Ed25519),
            sealing_alg: sealing_alg,
            encrypted_value: Vec::from(sealed_keypair),
            public_key: Some(Vec::from(public_key)),
            not_before: Some(not_before),
            not_after: Some(not_after),
            description: description,
        }
    }

    pub fn build_json(&self, builder: ObjectBuilder) -> ObjectBuilder {
        let builder = builder.insert("keyid", self.keyid.to_base64(base64::URL_SAFE))
            .insert("credential_type", self.credential_type.to_string())
            .insert("credential_alg", self.credential_type.protobuf_alg())
            .insert("sealing_alg", self.sealing_alg.to_string())
            .insert("encrypted_value",
                    self.encrypted_value.to_base64(base64::URL_SAFE));

        let builder = match self.public_key {
            Some(ref public_key) => {
                builder.insert("public_key", public_key.to_base64(base64::URL_SAFE))
            }
            None => builder,
        };

        let builder = match self.not_before {
            Some(ref not_before) => builder.insert("not_before", not_before),
            None => builder,
        };

        let builder = match self.not_after {
            Some(ref not_after) => builder.insert("not_after", not_after),
            None => builder,
        };

        let builder = match self.description {
            Some(ref description) => builder.insert("description", description),
            None => builder,
        };

        builder
    }
}

impl ToProto for CredentialObject {}

impl Serialize for CredentialObject {
    fn serialize<O: OutputStream>(&self, out: &mut O) -> io::Result<()> {
        try!(out.write(1, &self.keyid));
        try!(out.write(2, &self.credential_type.protobuf_id()));
        try!(out.write(3, &self.credential_type.protobuf_alg()));
        try!(out.write(4, &self.sealing_alg.protobuf_id()));
        try!(out.write(5, &self.encrypted_value));

        if let Some(ref public_key) = self.public_key {
            try!(out.write(6, public_key));
        }

        if let Some(not_before) = self.not_before {
            try!(out.write(7, &not_before));
        }

        if let Some(not_after) = self.not_after {
            try!(out.write(8, &not_after));
        }

        if let Some(ref description) = self.description {
            try!(out.write(9, description));
        }

        Ok(())
    }
}

impl Deserialize for CredentialObject {
    fn deserialize<R: io::Read>(i: &mut InputStream<R>) -> io::Result<CredentialObject> {
        let mut keyid: Option<Vec<u8>> = None;
        let mut credential_id: Option<u32> = None;
        let mut credential_alg: Option<String> = None;
        let mut _sealing_alg: Option<u32> = None;
        let mut encrypted_value: Option<Vec<u8>> = None;
        let mut public_key: Option<Vec<u8>> = None;
        let mut not_before: Option<u64> = None;
        let mut not_after: Option<u64> = None;
        let mut description: Option<String> = None;

        while let Some(f) = try!(i.read_field()) {
            match f.tag() {
                1 => keyid = Some(try!(f.read())),
                2 => credential_id = Some(try!(f.read())),
                3 => credential_alg = Some(try!(f.read())),
                4 => _sealing_alg = Some(try!(f.read())),
                5 => encrypted_value = Some(try!(f.read())),
                6 => public_key = Some(try!(f.read())),
                7 => not_before = Some(try!(f.read())),
                8 => not_after = Some(try!(f.read())),
                9 => description = Some(try!(f.read())),
                _ => try!(f.skip()),
            }
        }

        let credential_type = try!(Type::from_id_and_alg(credential_id, credential_alg)
            .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid credential type")));

        Ok(CredentialObject {
            keyid: required!(keyid, "CredentialObject::keyid"),
            credential_type: credential_type,
            sealing_alg: EncryptionAlgorithm::Aes256Gcm, // TODO: actually parse this
            encrypted_value: required!(encrypted_value, "CredentialObject::encrypted_value"),
            public_key: public_key,
            not_before: not_before,
            not_after: not_after,
            description: description,
        })
    }
}

impl ObjectHash for CredentialObject {
    #[inline]
    fn objecthash<H: ObjectHasher>(&self, hasher: &mut H) {
        let mut digests: Vec<Vec<u8>> = Vec::new();

        let credential_id_string = self.credential_type.to_string();
        let credential_alg_string = self.credential_type.protobuf_alg();

        digests.push(objecthash_struct_member!("keyid", self.keyid));
        digests.push(objecthash_struct_member!("credential_type", credential_id_string));
        digests.push(objecthash_struct_member!("credential_alg", credential_alg_string));
        digests.push(objecthash_struct_member!("sealing_alg", self.sealing_alg.to_string()));
        digests.push(objecthash_struct_member!("encrypted_value", self.encrypted_value));

        if let Some(ref public_key) = self.public_key {
            digests.push(objecthash_struct_member!("public_key", *public_key));
        }

        if let Some(not_before) = self.not_before {
            digests.push(objecthash_struct_member!("not_before", not_before));
        }

        if let Some(not_after) = self.not_after {
            digests.push(objecthash_struct_member!("not_after", not_after));
        }

        if let Some(ref description) = self.description {
            digests.push(objecthash_struct_member!("description", *description));
        }

        digests.sort();

        hasher.update(objecthash::types::DICT_TAG);

        for value in &digests {
            hasher.update(&value);
        }
    }
}
<commit_msg>Verify sealing_alg specified in Credential proto<commit_after>use std::io;

use buffoon::{Serialize, Deserialize, OutputStream, InputStream};
use rustc_serialize::base64::{self, ToBase64};
use serde_json::builder::ObjectBuilder;

use algorithm::{EncryptionAlgorithm, SignatureAlgorithm};
use error::{Error, Result};
use proto::ToProto;
use objecthash::{self, ObjectHash, ObjectHasher};

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum Type {
    SignatureKeyPair(SignatureAlgorithm),
}

#[derive(Debug, Eq, PartialEq)]
pub struct CredentialObject {
    keyid: Vec<u8>,
    credential_type: Type,
    sealing_alg: EncryptionAlgorithm,
    encrypted_value: Vec<u8>,
    public_key: Option<Vec<u8>>,
    not_before: Option<u64>,
    not_after: Option<u64>,
    description: Option<String>,
}

impl Type {
    fn protobuf_id(&self) -> u32 {
        match *self {
            Type::SignatureKeyPair(_) => 1,
        }
    }

    fn protobuf_alg(&self) -> String {
        match *self {
            // TODO: factor this into SignatureAlgorithm
            Type::SignatureKeyPair(SignatureAlgorithm::Ed25519) => String::from("Ed25519"),
        }
    }

    // TODO: actually support more algorithms
    fn from_id_and_alg(credential_id: Option<u32>, credential_alg: Option<String>) -> Result<Type> {
        if credential_id != Some(1) {
            return Err(Error::Parse);
        }

        if credential_alg != Some(String::from("Ed25519")) {
            return Err(Error::Parse);
        }

        Ok(Type::SignatureKeyPair(SignatureAlgorithm::Ed25519))
    }
}

impl ToString for Type {
    fn to_string(&self) -> String {
        match *self {
            Type::SignatureKeyPair(_) => String::from("SIGNATURE_KEY_PAIR"),
        }
    }
}

impl CredentialObject {
    pub fn signature_keypair(sealing_alg: EncryptionAlgorithm,
                             signature_alg: SignatureAlgorithm,
                             sealed_keypair: &[u8],
                             public_key: &[u8],
                             not_before: u64,
                             not_after: u64,
                             description: Option<String>)
                             -> CredentialObject {
        // Ed25519 is the only signature algorithm we presently support
        assert!(signature_alg == SignatureAlgorithm::Ed25519);

        CredentialObject {
            keyid: Vec::from(public_key),
            credential_type: Type::SignatureKeyPair(SignatureAlgorithm::Ed25519),
            sealing_alg: sealing_alg,
            encrypted_value: Vec::from(sealed_keypair),
            public_key: Some(Vec::from(public_key)),
            not_before: Some(not_before),
            not_after: Some(not_after),
            description: description,
        }
    }

    pub fn build_json(&self, builder: ObjectBuilder) -> ObjectBuilder {
        let builder = builder.insert("keyid", self.keyid.to_base64(base64::URL_SAFE))
            .insert("credential_type", self.credential_type.to_string())
            .insert("credential_alg", self.credential_type.protobuf_alg())
            .insert("sealing_alg", self.sealing_alg.to_string())
            .insert("encrypted_value",
                    self.encrypted_value.to_base64(base64::URL_SAFE));

        let builder = match self.public_key {
            Some(ref public_key) => {
                builder.insert("public_key", public_key.to_base64(base64::URL_SAFE))
            }
            None => builder,
        };

        let builder = match self.not_before {
            Some(ref not_before) => builder.insert("not_before", not_before),
            None => builder,
        };

        let builder = match self.not_after {
            Some(ref not_after) => builder.insert("not_after", not_after),
            None => builder,
        };

        let builder = match self.description {
            Some(ref description) => builder.insert("description", description),
            None => builder,
        };

        builder
    }
}

impl ToProto for CredentialObject {}

impl Serialize for CredentialObject {
    fn serialize<O: OutputStream>(&self, out: &mut O) -> io::Result<()> {
        try!(out.write(1, &self.keyid));
        try!(out.write(2, &self.credential_type.protobuf_id()));
        try!(out.write(3, &self.credential_type.protobuf_alg()));
        try!(out.write(4, &self.sealing_alg.protobuf_id()));
        try!(out.write(5, &self.encrypted_value));

        if let Some(ref public_key) = self.public_key {
            try!(out.write(6, public_key));
        }

        if let Some(not_before) = self.not_before {
            try!(out.write(7, &not_before));
        }

        if let Some(not_after) = self.not_after {
            try!(out.write(8, &not_after));
        }

        if let Some(ref description) = self.description {
            try!(out.write(9, description));
        }

        Ok(())
    }
}

impl Deserialize for CredentialObject {
    fn deserialize<R: io::Read>(i: &mut InputStream<R>) -> io::Result<CredentialObject> {
        let mut keyid: Option<Vec<u8>> = None;
        let mut credential_id: Option<u32> = None;
        let mut credential_alg: Option<String> = None;
        let mut sealing_alg: Option<u32> = None;
        let mut encrypted_value: Option<Vec<u8>> = None;
        let mut public_key: Option<Vec<u8>> = None;
        let mut not_before: Option<u64> = None;
        let mut not_after: Option<u64> = None;
        let mut description: Option<String> = None;

        while let Some(f) = try!(i.read_field()) {
            match f.tag() {
                1 => keyid = Some(try!(f.read())),
                2 => credential_id = Some(try!(f.read())),
                3 => credential_alg = Some(try!(f.read())),
                4 => sealing_alg = Some(try!(f.read())),
                5 => encrypted_value = Some(try!(f.read())),
                6 => public_key = Some(try!(f.read())),
                7 => not_before = Some(try!(f.read())),
                8 => not_after = Some(try!(f.read())),
                9 => description = Some(try!(f.read())),
                _ => try!(f.skip()),
            }
        }

        let credential_type = try!(Type::from_id_and_alg(credential_id, credential_alg)
            .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid credential type")));

        // Ensure sealing algorithm is Aes256Gcm
        if sealing_alg != Some(EncryptionAlgorithm::Aes256Gcm.protobuf_id()) {
            return Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid sealing algorithm"));
        }

        Ok(CredentialObject {
            keyid: required!(keyid, "CredentialObject::keyid"),
            credential_type: credential_type,
            sealing_alg: EncryptionAlgorithm::Aes256Gcm,
            encrypted_value: required!(encrypted_value, "CredentialObject::encrypted_value"),
            public_key: public_key,
            not_before: not_before,
            not_after: not_after,
            description: description,
        })
    }
}

impl ObjectHash for CredentialObject {
    #[inline]
    fn objecthash<H: ObjectHasher>(&self, hasher: &mut H) {
        let mut digests: Vec<Vec<u8>> = Vec::new();

        let credential_id_string = self.credential_type.to_string();
        let credential_alg_string = self.credential_type.protobuf_alg();

        digests.push(objecthash_struct_member!("keyid", self.keyid));
        digests.push(objecthash_struct_member!("credential_type", credential_id_string));
        digests.push(objecthash_struct_member!("credential_alg", credential_alg_string));
        digests.push(objecthash_struct_member!("sealing_alg", self.sealing_alg.to_string()));
        digests.push(objecthash_struct_member!("encrypted_value", self.encrypted_value));

        if let Some(ref public_key) = self.public_key {
            digests.push(objecthash_struct_member!("public_key", *public_key));
        }

        if let Some(not_before) = self.not_before {
            digests.push(objecthash_struct_member!("not_before", not_before));
        }

        if let Some(not_after) = self.not_after {
            digests.push(objecthash_struct_member!("not_after", not_after));
        }

        if let Some(ref description) = self.description {
            digests.push(objecthash_struct_member!("description", *description));
        }

        digests.sort();

        hasher.update(objecthash::types::DICT_TAG);

        for value in &digests {
            hasher.update(&value);
        }
    }
}
<|endoftext|>


<commit_before>/// Enum mapping type
///
/// This trait is internally used by `#[derive(Enum)]`.  `Internal<T>` is
/// implemented by any enum type where V is a generic type representing a
/// value. The purpose of this generic type is to allow providing a value
/// type for arrays, as Rust currently does not support higher kinded types.
///
/// This trait is also implemented by `bool` and `u8`. While `u8` is
/// strictly speaking not an actual enum, there are good reasons to consider
/// it like one, as array of `u8` keys is a relatively common pattern.
pub trait Enum<V>: Sized {
    /// Representation of an enum map for type `V`, usually an array.
    type Array;
    /// Number of possible values the type can have.
    const POSSIBLE_VALUES: usize;
    #[doc(hidden)]
    fn slice(array: &Self::Array) -> &[V];
    #[doc(hidden)]
    fn slice_mut(array: &mut Self::Array) -> &mut [V];
    #[doc(hidden)]
    fn from_usize(value: usize) -> Self;
    #[doc(hidden)]
    fn to_usize(self) -> usize;
    #[doc(hidden)]
    fn from_function<F: FnMut(Self) -> V>(f: F) -> Self::Array;
}

impl<T> Enum<T> for bool {
    type Array = [T; 2];
    const POSSIBLE_VALUES: usize = 2;
    fn slice(array: &[T; 2]) -> &[T] {
        array
    }
    fn slice_mut(array: &mut [T; 2]) -> &mut [T] {
        array
    }
    fn from_usize(value: usize) -> Self {
        match value {
            0 => false,
            1 => true,
            _ => unreachable!(),
        }
    }
    fn to_usize(self) -> usize {
        self as usize
    }
    fn from_function<F: FnMut(Self) -> T>(mut f: F) -> [T; 2] {
        [f(false), f(true)]
    }
}

impl<T> Enum<T> for u8 {
    type Array = [T; 256];
    const POSSIBLE_VALUES: usize = 256;
    fn slice(array: &[T; 256]) -> &[T] {
        array
    }
    fn slice_mut(array: &mut [T; 256]) -> &mut [T] {
        array
    }
    fn from_usize(value: usize) -> Self {
        value as u8
    }
    fn to_usize(self) -> usize {
        self as usize
    }
    fn from_function<F: FnMut(Self) -> T>(mut f: F) -> [T; 256] {
        array![|i| f(i as u8); 256]
    }
}

// C representation is needed to ensure Rust compiler won't reorder those 2 fields.
#[repr(C)]
#[derive(Copy, Clone)]
pub struct OptionInternal<T, U> {
    none: T,
    some: U,
}
<commit_msg>Document Enum trait<commit_after>/// Enum mapping type
///
/// This trait is internally used by `#[derive(Enum)]`.  `Enum<T>` is
/// implemented by any enum type where V is a generic type representing a
/// value. The purpose of this generic type is to allow providing a value
/// type for arrays, as Rust currently does not support higher kinded types.
///
/// This trait is also implemented by `bool` and `u8`. While `u8` is
/// strictly speaking not an actual enum, there are good reasons to consider
/// it like one, as array of `u8` keys is a relatively common pattern.
pub trait Enum<V>: Sized {
    /// Representation of an enum map for type `V`, usually an array.
    type Array;
    /// Number of possible values the type can have.
    const POSSIBLE_VALUES: usize;
    /// Gets a slice from an array type.
    fn slice(array: &Self::Array) -> &[V];
    /// Gets a mutable slice from an array type.
    fn slice_mut(array: &mut Self::Array) -> &mut [V];
    /// Takes an usize, and returns an element matching `to_usize` function.
    fn from_usize(value: usize) -> Self;
    /// Returns an unique identifier for a value within range of `0..POSSIBLE_VALUES`.
    fn to_usize(self) -> usize;
    /// Creates an array using a function called for each argument.
    fn from_function<F: FnMut(Self) -> V>(f: F) -> Self::Array;
}

impl<T> Enum<T> for bool {
    type Array = [T; 2];
    const POSSIBLE_VALUES: usize = 2;
    fn slice(array: &[T; 2]) -> &[T] {
        array
    }
    fn slice_mut(array: &mut [T; 2]) -> &mut [T] {
        array
    }
    fn from_usize(value: usize) -> Self {
        match value {
            0 => false,
            1 => true,
            _ => unreachable!(),
        }
    }
    fn to_usize(self) -> usize {
        self as usize
    }
    fn from_function<F: FnMut(Self) -> T>(mut f: F) -> [T; 2] {
        [f(false), f(true)]
    }
}

impl<T> Enum<T> for u8 {
    type Array = [T; 256];
    const POSSIBLE_VALUES: usize = 256;
    fn slice(array: &[T; 256]) -> &[T] {
        array
    }
    fn slice_mut(array: &mut [T; 256]) -> &mut [T] {
        array
    }
    fn from_usize(value: usize) -> Self {
        value as u8
    }
    fn to_usize(self) -> usize {
        self as usize
    }
    fn from_function<F: FnMut(Self) -> T>(mut f: F) -> [T; 256] {
        array![|i| f(i as u8); 256]
    }
}

// C representation is needed to ensure Rust compiler won't reorder those 2 fields.
#[repr(C)]
#[derive(Copy, Clone)]
pub struct OptionInternal<T, U> {
    none: T,
    some: U,
}
<|endoftext|>


<commit_before>use std::default::Default;
use std::ops::Add;

/// Stats specifies static bonuses for an entity. Stats values can be added
/// together to build composites. The Default value for Stats must be an
/// algebraic zero element, adding it to any Stats value must leave that value
/// unchanged.
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
pub struct Stats {
    /// Generic power level
    pub power: i32,
    /// Attack bonus
    pub attack: i32,
    /// Damage reduction
    pub protection: i32,
    /// Mana pool / mana drain
    pub mana: i32,
    /// Ranged attack range. Zero means no ranged capability.
    pub ranged_range: u32,
    /// Ranged attack power
    pub ranged_power: i32,

    /// Bit flags for intrinsics
    pub intrinsics: u32,
}

impl Stats {
    pub fn new(power: i32, intrinsics: &[Intrinsic]) -> Stats {
        let mut intr = 0u32;
        for &i in intrinsics.iter() {
            intr |= i as u32;
        }
        Stats {
            power: power,
            intrinsics: intr,
            ..Default::default()
        }
    }

    pub fn mana(self, mana: i32) -> Stats { Stats { mana: mana, ..self } }
    pub fn protection(self, protection: i32) -> Stats {
        Stats {
            protection: protection,
            ..self
        }
    }
    pub fn attack(self, attack: i32) -> Stats {
        Stats {
            attack: attack,
            ..self
        }
    }
    pub fn ranged_range(self, ranged_range: u32) -> Stats {
        Stats {
            ranged_range: ranged_range,
            ..self
        }
    }
    pub fn ranged_power(self, ranged_power: i32) -> Stats {
        Stats {
            ranged_power: ranged_power,
            ..self
        }
    }
}

impl Add<Stats> for Stats {
    type Output = Stats;
    fn add(self, other: Stats) -> Stats {
        Stats {
            power: self.power + other.power,
            attack: self.attack + other.attack,
            protection: self.protection + other.protection,
            mana: self.mana + other.mana,
            // XXX: Must be careful to have exactly one "ranged weapon" item
            // in the mix. A mob with a natural ranged attack equipping a
            // ranged weapon should *not* have the ranges added together.
            // On the other hand a "sniper scope" trinket could be a +2 range
            // type dealie.
            ranged_range: self.ranged_range + other.ranged_range,
            ranged_power: self.ranged_power + other.ranged_power,
            intrinsics: self.intrinsics | other.intrinsics,
        }
    }
}

#[derive(Copy, Eq, PartialEq, Clone, Debug, Serialize, Deserialize)]
pub enum Intrinsic {
    /// Moves 1/3 slower than usual.
    Slow = 0b1,
    /// Moves 1/3 faster than usual, stacks with Quick status.
    Fast = 0b10,
    /// Moves 1/3 faster than usual, stacks with Fast status.
    Quick = 0b100,
    /// Can manipulate objects and doors.
    Hands = 0b1000,
    /// Explodes on death
    Deathsplosion = 0b10000,
    /// Is dead (not undead-dead, no-longer-subject-to-animate-things-logic-dead)
    Dead = 0b100000,
}
<commit_msg>Look over stats for combat logic<commit_after>use std::default::Default;
use std::ops::Add;

/// Stats specifies static bonuses for an entity. Stats values can be added
/// together to build composites. The Default value for Stats must be an
/// algebraic zero element, adding it to any Stats value must leave that value
/// unchanged.
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
pub struct Stats {
    /// Generic power level
    pub power: i32,
    /// Attack bonus
    pub attack: i32,
    /// Defense bonus
    pub defense: i32,
    /// Damage reduction
    pub armor: i32,
    /// Mana pool / mana drain
    pub mana: i32,
    /// Ranged attack range. Zero means no ranged capability.
    pub ranged_range: u32,
    /// Ranged attack power
    pub ranged_power: i32,

    /// Bit flags for intrinsics
    pub intrinsics: u32,
}

impl Stats {
    pub fn new(power: i32, intrinsics: &[Intrinsic]) -> Stats {
        let intrinsics = intrinsics.iter().fold(0, |acc, &i| acc | i as u32);
        Stats {
            power,
            intrinsics,
            ..Default::default()
        }
    }

    pub fn mana(self, mana: i32) -> Stats { Stats { mana, ..self } }
    pub fn armor(self, armor: i32) -> Stats { Stats { armor, ..self } }
    pub fn attack(self, attack: i32) -> Stats { Stats { attack, ..self } }
    pub fn defense(self, defense: i32) -> Stats { Stats { defense, ..self } }
    pub fn ranged_range(self, ranged_range: u32) -> Stats {
        Stats {
            ranged_range,
            ..self
        }
    }
    pub fn ranged_power(self, ranged_power: i32) -> Stats {
        Stats {
            ranged_power,
            ..self
        }
    }
}

impl Add<Stats> for Stats {
    type Output = Stats;
    fn add(self, other: Stats) -> Stats {
        Stats {
            power: self.power + other.power,
            attack: self.attack + other.attack,
            defense: self.defense + other.defense,
            armor: self.armor + other.armor,
            mana: self.mana + other.mana,
            // XXX: Must be careful to have exactly one "ranged weapon" item
            // in the mix. A mob with a natural ranged attack equipping a
            // ranged weapon should *not* have the ranges added together.
            // On the other hand a "sniper scope" trinket could be a +2 range
            // type dealie.
            ranged_range: self.ranged_range + other.ranged_range,
            ranged_power: self.ranged_power + other.ranged_power,
            intrinsics: self.intrinsics | other.intrinsics,
        }
    }
}

#[derive(Copy, Eq, PartialEq, Clone, Debug, Serialize, Deserialize)]
pub enum Intrinsic {
    /// Moves 1/3 slower than usual.
    Slow = 0b1,
    /// Moves 1/3 faster than usual, stacks with Quick status.
    Fast = 0b10,
    /// Moves 1/3 faster than usual, stacks with Fast status.
    Quick = 0b100,
    /// Can manipulate objects and doors.
    Hands = 0b1000,
    /// Explodes on death
    Deathsplosion = 0b10000,
    /// Is dead (not undead-dead, no-longer-subject-to-animate-things-logic-dead)
    Dead = 0b100000,
}
<|endoftext|>


<commit_before>/*
 * Copyright 2017-2018 Ben Ashford
 *
 * 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.
 */

//! The client API itself.
//!
//! This contains three main functions that return three specific types of client:
//!
//! * `connect` returns a pair of `Stream` and `Sink`, clients can write RESP messages to the
//! `Sink` and read RESP messages from the `Stream`. Pairing requests to responses is up to the
//! client.  This is intended to be a low-level interface from which more user-friendly interfaces
//! can be built.
//! * `paired_connect` is used for most of the standard Redis commands, where one request results
//! in one response.
//! * `pubsub_connect` is used for Redis's PUBSUB functionality.

pub mod connect;
#[macro_use]
pub mod paired;
pub mod pubsub;

pub use self::{connect::connect, paired::{paired_connect, PairedConnection},
               pubsub::{pubsub_connect, PubsubConnection}};

#[cfg(test)]
mod test {
    use std::io;

    use futures::sync::oneshot;
    use futures::{stream, Future, Sink, Stream};

    use tokio;

    use error;
    use resp;

    fn run_and_wait<R, E, F>(f: F) -> Result<R, E>
    where
        F: Future<Item = R, Error = E> + Send + 'static,
        R: Send + 'static,
        E: Send + 'static,
    {
        let (tx, rx) = oneshot::channel();
        tokio::run(f.then(|r| tx.send(r).map_err(|_| panic!("Cannot send Result"))));
        rx.wait().expect("Cannot wait for a result")
    }

    #[test]
    fn can_connect() {
        let addr = "127.0.0.1:6379".parse().unwrap();

        let connection = super::connect(&addr)
            .map_err(|e| e.into())
            .and_then(|connection| {
                connection
                    .send(resp_array!["PING", "TEST"])
                    .map_err(|e| e.into())
            })
            .and_then(|connection| connection.take(1).collect());

        let values = run_and_wait(connection).unwrap();

        assert_eq!(values.len(), 1);
        assert_eq!(values[0], "TEST".into());
    }

    #[test]
    fn complex_test() {
        // TODO - unimplemented
        //
        // let addr = "127.0.0.1:6379".parse().unwrap();
        // let connection = super::connect(&addr)
        //     .map_err(|e| e.into())
        //     .and_then(|connection| {
        //         let mut ops = Vec::<resp::RespValue>::new();
        //         ops.push(resp_array!["FLUSH"]);
        //         ops.extend(
        //             (0..1000).map(|i| resp_array!["SADD", "test_set", format!("VALUE: {}", i)]),
        //         );
        //         ops.push(resp_array!["SMEMBERS", "test_set"]);
        //         let send = connection
        //             .sender
        //             .send_all(stream::iter_ok::<_, io::Error>(ops))
        //             .map(|(sender, _)| sender)
        //             .map_err(|e| e.into());
        //         let receive = connection.receiver.skip(1001).take(1).collect();
        //         send.join(receive).and_then(|(sender, values)| {
        //             close_sender(sender).map_err(|e| e.into()).map(|()| values)
        //         })
        //     });
        // let values = run_and_wait(connection).unwrap();
        // assert_eq!(values.len(), 1);
        // let values = match &values[0] {
        //     &resp::RespValue::Array(ref values) => values.clone(),
        //     _ => panic!("Not an array"),
        // };
        // assert_eq!(values.len(), 1000);
    }

    #[test]
    fn can_paired_connect() {
        let addr = "127.0.0.1:6379".parse().unwrap();

        let connect_f = super::paired_connect(&addr).and_then(|connection| {
            let res_f = connection.send(resp_array!["PING", "TEST"]);
            faf!(connection.send(resp_array!["SET", "X", "123"]));
            let wait_f = connection.send(resp_array!["GET", "X"]);
            res_f.join(wait_f)
        });
        let (result_1, result_2): (String, String) = run_and_wait(connect_f).unwrap();
        assert_eq!(result_1, "TEST");
        assert_eq!(result_2, "123");
    }

    #[test]
    fn complex_paired_connect() {
        // let addr = "127.0.0.1:6379".parse().unwrap();

        // let connect_f = super::paired_connect(&addr).and_then(|connection| {
        //     connection
        //         .send(resp_array!["INCR", "CTR"])
        //         .and_then(move |value: String| {
        //             connection.send(resp_array!["SET", "LASTCTR", value])
        //         })
        // });
        // let result: String = run_and_wait(connect_f).unwrap();
        // assert_eq!(result, "OK");
    }

    #[test]
    fn sending_a_lot_of_data_test() {
        // let addr = "127.0.0.1:6379".parse().unwrap();

        // let test_f = super::paired_connect(&addr);
        // let send_data = test_f.and_then(|connection| {
        //     let mut futures = Vec::with_capacity(1000);
        //     for i in 0..1000 {
        //         let key = format!("X_{}", i);
        //         faf!(connection.send(resp_array!["SET", &key, i.to_string()]));
        //         futures.push(connection.send(resp_array!["GET", key]));
        //     }
        //     futures.remove(999)
        // });
        // let result: String = run_and_wait(send_data).unwrap();
        // assert_eq!(result, "999");
    }

    #[test]
    fn pubsub_test() {
        // let addr = "127.0.0.1:6379".parse().unwrap();
        // let paired_c = super::paired_connect(&addr);
        // let pubsub_c = super::pubsub_connect(&addr);
        // let msgs = paired_c.join(pubsub_c).and_then(|(paired, pubsub)| {
        //     let subscribe = pubsub.subscribe("test-topic");
        //     subscribe.and_then(move |msgs| {
        //         faf!(paired.send(resp_array!["PUBLISH", "test-topic", "test-message"]));
        //         faf!(paired.send(resp_array!["PUBLISH", "test-not-topic", "test-message-1.5"]));
        //         paired
        //             .send(resp_array!["PUBLISH", "test-topic", "test-message2"])
        //             .map(|_: resp::RespValue| msgs)
        //     })
        // });
        // let tst = msgs.and_then(|msgs| {
        //     msgs.take(2)
        //         .collect()
        //         .map_err(|_| error::internal("unreachable"))
        // });
        // let result = run_and_wait(tst).unwrap();
        // assert_eq!(result.len(), 2);
        // assert_eq!(result[0], "test-message".into());
        // assert_eq!(result[1], "test-message2".into());
    }
}
<commit_msg>Re-enabled test<commit_after>/*
 * Copyright 2017-2018 Ben Ashford
 *
 * 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.
 */

//! The client API itself.
//!
//! This contains three main functions that return three specific types of client:
//!
//! * `connect` returns a pair of `Stream` and `Sink`, clients can write RESP messages to the
//! `Sink` and read RESP messages from the `Stream`. Pairing requests to responses is up to the
//! client.  This is intended to be a low-level interface from which more user-friendly interfaces
//! can be built.
//! * `paired_connect` is used for most of the standard Redis commands, where one request results
//! in one response.
//! * `pubsub_connect` is used for Redis's PUBSUB functionality.

pub mod connect;
#[macro_use]
pub mod paired;
pub mod pubsub;

pub use self::{connect::connect, paired::{paired_connect, PairedConnection},
               pubsub::{pubsub_connect, PubsubConnection}};

#[cfg(test)]
mod test {
    use std::io;

    use futures::sync::oneshot;
    use futures::{stream, Future, Sink, Stream};

    use tokio;

    use error;
    use resp;

    fn run_and_wait<R, E, F>(f: F) -> Result<R, E>
    where
        F: Future<Item = R, Error = E> + Send + 'static,
        R: Send + 'static,
        E: Send + 'static,
    {
        let (tx, rx) = oneshot::channel();
        tokio::run(f.then(|r| tx.send(r).map_err(|_| panic!("Cannot send Result"))));
        rx.wait().expect("Cannot wait for a result")
    }

    #[test]
    fn can_connect() {
        let addr = "127.0.0.1:6379".parse().unwrap();

        let connection = super::connect(&addr)
            .map_err(|e| e.into())
            .and_then(|connection| {
                connection
                    .send(resp_array!["PING", "TEST"])
                    .map_err(|e| e.into())
            })
            .and_then(|connection| connection.take(1).collect());

        let values = run_and_wait(connection).unwrap();

        assert_eq!(values.len(), 1);
        assert_eq!(values[0], "TEST".into());
    }

    #[test]
    fn complex_test() {
        let addr = "127.0.0.1:6379".parse().unwrap();
        let connection = super::connect(&addr)
            .map_err(|e| e.into())
            .and_then(|connection| {
                let mut ops = Vec::<resp::RespValue>::new();
                ops.push(resp_array!["FLUSH"]);
                ops.extend(
                    (0..1000).map(|i| resp_array!["SADD", "test_set", format!("VALUE: {}", i)]),
                );
                ops.push(resp_array!["SMEMBERS", "test_set"]);
                let send_f = connection
                    .send_all(stream::iter_ok::<_, io::Error>(ops))
                    .map(|(sender, _)| sender)
                    .map_err(|e| e.into());
                send_f.and_then(|connection| connection.skip(1001).take(1).collect())
            });
        let values = run_and_wait(connection).unwrap();
        assert_eq!(values.len(), 1);
        let values = match &values[0] {
            &resp::RespValue::Array(ref values) => values.clone(),
            _ => panic!("Not an array"),
        };
        assert_eq!(values.len(), 1000);
    }

    #[test]
    fn can_paired_connect() {
        let addr = "127.0.0.1:6379".parse().unwrap();

        let connect_f = super::paired_connect(&addr).and_then(|connection| {
            let res_f = connection.send(resp_array!["PING", "TEST"]);
            faf!(connection.send(resp_array!["SET", "X", "123"]));
            let wait_f = connection.send(resp_array!["GET", "X"]);
            res_f.join(wait_f)
        });
        let (result_1, result_2): (String, String) = run_and_wait(connect_f).unwrap();
        assert_eq!(result_1, "TEST");
        assert_eq!(result_2, "123");
    }

    #[test]
    fn complex_paired_connect() {
        // let addr = "127.0.0.1:6379".parse().unwrap();

        // let connect_f = super::paired_connect(&addr).and_then(|connection| {
        //     connection
        //         .send(resp_array!["INCR", "CTR"])
        //         .and_then(move |value: String| {
        //             connection.send(resp_array!["SET", "LASTCTR", value])
        //         })
        // });
        // let result: String = run_and_wait(connect_f).unwrap();
        // assert_eq!(result, "OK");
    }

    #[test]
    fn sending_a_lot_of_data_test() {
        // let addr = "127.0.0.1:6379".parse().unwrap();

        // let test_f = super::paired_connect(&addr);
        // let send_data = test_f.and_then(|connection| {
        //     let mut futures = Vec::with_capacity(1000);
        //     for i in 0..1000 {
        //         let key = format!("X_{}", i);
        //         faf!(connection.send(resp_array!["SET", &key, i.to_string()]));
        //         futures.push(connection.send(resp_array!["GET", key]));
        //     }
        //     futures.remove(999)
        // });
        // let result: String = run_and_wait(send_data).unwrap();
        // assert_eq!(result, "999");
    }

    #[test]
    fn pubsub_test() {
        // let addr = "127.0.0.1:6379".parse().unwrap();
        // let paired_c = super::paired_connect(&addr);
        // let pubsub_c = super::pubsub_connect(&addr);
        // let msgs = paired_c.join(pubsub_c).and_then(|(paired, pubsub)| {
        //     let subscribe = pubsub.subscribe("test-topic");
        //     subscribe.and_then(move |msgs| {
        //         faf!(paired.send(resp_array!["PUBLISH", "test-topic", "test-message"]));
        //         faf!(paired.send(resp_array!["PUBLISH", "test-not-topic", "test-message-1.5"]));
        //         paired
        //             .send(resp_array!["PUBLISH", "test-topic", "test-message2"])
        //             .map(|_: resp::RespValue| msgs)
        //     })
        // });
        // let tst = msgs.and_then(|msgs| {
        //     msgs.take(2)
        //         .collect()
        //         .map_err(|_| error::internal("unreachable"))
        // });
        // let result = run_and_wait(tst).unwrap();
        // assert_eq!(result.len(), 2);
        // assert_eq!(result[0], "test-message".into());
        // assert_eq!(result[1], "test-message2".into());
    }
}
<|endoftext|>


<commit_before>extern crate tokio;
extern crate futures;
use self::tokio::{Service, client};
use self::tokio::tcp::TcpStream;
use self::tokio::reactor::*;
use self::tokio::io::{TryWrite, TryRead, Readiness, Transport};
use self::tokio::proto::pipeline;
use self::tokio::proto::pipeline::{Server, Frame};
use self::futures::{done, Future};
use std::io;

use super::parse::{Command, CommandParser};

pub struct Client {}
impl Client {
    pub fn start() {
        let reactor = Reactor::default().unwrap();

        let stream = TcpStream::connect(&"127.0.0.1:6667".parse().unwrap()).unwrap();
        let server = Server::new(tokio::simple_service(|r| {
            futures::done(Ok(CommandParser::new(b"NICK nickmass".to_vec()).parse()))
        })
        , IrcTransport::new(stream)).unwrap();
        let handle = &reactor.handle();

        handle.schedule(server);

        reactor.run().unwrap();
    }
}

enum ServiceError {
    Transport(TransportError),
    Service,
}

impl From<pipeline::Error<TransportError>> for ServiceError {
    fn from(e: pipeline::Error<TransportError>) -> Self {
        ServiceError::Service
    }
}
impl From<TransportError> for ServiceError {
    fn from(e: TransportError) -> Self {
        ServiceError::Transport(e)
    }
}

enum TransportError {
    Something,
    Bad
}

struct IrcService {}
impl IrcService {
    fn new() -> IrcService {
        IrcService {}
    }
}

impl Service for IrcService {
    type Req = String;
    type Resp = Command;
    type Error = ServiceError;
    type Fut = Box<Future<Item = Self::Resp, Error = Self::Error>>;

    fn call(&self, req: String) -> Self::Fut {
        println!("Req: {:?}", req);
    }
}

struct IrcTransport<T> {
    stream: T,
    read_buf: Vec<u8>,
    write_buf: Vec<u8>,
}

impl<T: TryRead + TryWrite + Readiness> IrcTransport<T> {
    fn new(stream: T) -> IrcTransport<T> {
        let mut write_buf = Vec::new();
        write_buf.append(&mut b"USER nickmass 8 * :Nick Massey\r\n".to_vec());
        write_buf.append(&mut b"NICK nickmass\r\n".to_vec());
        IrcTransport { stream: stream, read_buf: Vec::new(), write_buf: write_buf }
    }
}

impl<T> Readiness for IrcTransport<T> {
    fn is_readable(&self) -> bool {
        true
    }

    fn is_writable(&self) -> bool {
        true
    }
}

impl<T: TryRead + TryWrite + Readiness> Transport for IrcTransport<T> {
    type In = Command;
    type Out = String;

    fn read(&mut self) -> io::Result<Option<Self::Out>> {
        let mut buf = Vec::new();
        if let Some(bytes) = try!(self.stream.try_read(&mut buf)) {
            if bytes > 0 {
                println!("read");
                println!("{}", ::std::str::from_utf8(&*buf).unwrap());
                buf.truncate(bytes);
                let mut count = 0;
                for i in &*buf {
                    count += 1;
                    if *i == 0x10 {
                        break;
                    }
                }

                let remainder = buf.split_off(count);
                self.read_buf.append(&mut buf);
                if self.read_buf.len() > 0 {
                    println!("{}", ::std::str::from_utf8(&*self.read_buf).unwrap());
                    return Ok(Some(String::from_utf8(self.read_buf.clone()).unwrap()));
                }
                self.read_buf = remainder;
            }
        }
        Ok(None)
    }

    fn write(&mut self, req: Self::In) -> io::Result<Option<()>>{
        self.write_buf.append(&mut req.to_cmd().into_bytes());
        if self.write_buf.len() > 0 {
            if let Some(bytes) = try!(self.stream.try_write(&*self.write_buf)) {
                println!("{}", ::std::str::from_utf8(&*self.write_buf).unwrap());
                self.write_buf = self.write_buf.split_off(bytes);
                return Ok(Some(()));
            }
        }
        Ok(None)
    }

    fn flush(&mut self) -> io::Result<Option<()>>{
        Ok(None)
    }
}
<commit_msg>Tweak future<commit_after>extern crate tokio;
extern crate futures;
use self::tokio::{Service, client};
use self::tokio::tcp::TcpStream;
use self::tokio::reactor::*;
use self::tokio::io::{TryWrite, TryRead, Readiness, Transport};
use self::tokio::proto::pipeline;
use self::tokio::proto::pipeline::{Server, Frame};
use self::futures::{Future};
use std::io;

use super::parse::{Command, CommandParser};

pub struct Client {}
impl Client {
    pub fn start() {
        let reactor = Reactor::default().unwrap();

        let stream = TcpStream::connect(&"127.0.0.1:6667".parse().unwrap()).unwrap();
        let server = Server::new(tokio::simple_service(|r| {
            Ok(CommandParser::new(b"NICK nickmass".to_vec()).parse())
        })
        , IrcTransport::new(stream)).unwrap();
        let handle = &reactor.handle();

        handle.schedule(server);

        reactor.run().unwrap();
    }
}

enum ServiceError {
    Transport(TransportError),
    Service,
}

impl From<pipeline::Error<TransportError>> for ServiceError {
    fn from(e: pipeline::Error<TransportError>) -> Self {
        ServiceError::Service
    }
}
impl From<TransportError> for ServiceError {
    fn from(e: TransportError) -> Self {
        ServiceError::Transport(e)
    }
}

enum TransportError {
    Something,
    Bad
}

struct IrcService {}
impl IrcService {
    fn new() -> IrcService {
        IrcService {}
    }
}

impl Service for IrcService {
    type Req = String;
    type Resp = Command;
    type Error = ServiceError;
    type Fut = Box<Future<Item = Self::Resp, Error = Self::Error>>;

    fn call(&self, req: String) -> Self::Fut {
        println!("Req: {:?}", req);
    }
}

struct IrcTransport<T> {
    stream: T,
    read_buf: Vec<u8>,
    write_buf: Vec<u8>,
}

impl<T: TryRead + TryWrite + Readiness> IrcTransport<T> {
    fn new(stream: T) -> IrcTransport<T> {
        let mut write_buf = Vec::new();
        write_buf.append(&mut b"USER nickmass 8 * :Nick Massey\r\n".to_vec());
        write_buf.append(&mut b"NICK nickmass\r\n".to_vec());
        IrcTransport { stream: stream, read_buf: Vec::new(), write_buf: write_buf }
    }
}

impl<T> Readiness for IrcTransport<T> {
    fn is_readable(&self) -> bool {
        true
    }

    fn is_writable(&self) -> bool {
        true
    }
}

impl<T: TryRead + TryWrite + Readiness> Transport for IrcTransport<T> {
    type In = Command;
    type Out = String;

    fn read(&mut self) -> io::Result<Option<Self::Out>> {
        let mut buf = Vec::new();
        if let Some(bytes) = try!(self.stream.try_read(&mut buf)) {
            if bytes > 0 {
                println!("read");
                println!("{}", ::std::str::from_utf8(&*buf).unwrap());
                buf.truncate(bytes);
                let mut count = 0;
                for i in &*buf {
                    count += 1;
                    if *i == 0x10 {
                        break;
                    }
                }

                let remainder = buf.split_off(count);
                self.read_buf.append(&mut buf);
                if self.read_buf.len() > 0 {
                    println!("{}", ::std::str::from_utf8(&*self.read_buf).unwrap());
                    return Ok(Some(String::from_utf8(self.read_buf.clone()).unwrap()));
                }
                self.read_buf = remainder;
            }
        }
        Ok(None)
    }

    fn write(&mut self, req: Self::In) -> io::Result<Option<()>>{
        self.write_buf.append(&mut req.to_cmd().into_bytes());
        if self.write_buf.len() > 0 {
            if let Some(bytes) = try!(self.stream.try_write(&*self.write_buf)) {
                println!("{}", ::std::str::from_utf8(&*self.write_buf).unwrap());
                self.write_buf = self.write_buf.split_off(bytes);
                return Ok(Some(()));
            }
        }
        Ok(None)
    }

    fn flush(&mut self) -> io::Result<Option<()>>{
        Ok(None)
    }
}
<|endoftext|>


<commit_before>use futures::{Async, Future, Poll, Sink};
use futures::stream::Stream;
use futures::sink::Send;
use futures_state_stream::{StateStream, StreamEvent};

use native_tls::TlsConnector;

use std::io;
use std::net::ToSocketAddrs;

use tokio::net::{ConnectFuture, TcpStream};
use tokio_io::AsyncRead;
use tokio_tls::{ConnectAsync, TlsConnectorExt};

use imap_proto::{Request, RequestId, State};
use imap_proto::builders::command::Command;
use proto::{ImapCodec, ImapTransport, ResponseData};

pub mod builder {
    pub use imap_proto::builders::command::{CommandBuilder, FetchBuilderAttributes,
                                            FetchBuilderMessages, FetchBuilderModifiers,
                                            FetchCommand, FetchCommandAttributes,
                                            FetchCommandMessages};
}

pub struct Client {
    transport: ImapTransport,
    state: ClientState,
}

impl Client {
    pub fn connect(server: &str) -> io::Result<ImapConnectFuture> {
        let addr = (server, 993).to_socket_addrs()?.next().ok_or_else(|| {
            io::Error::new(io::ErrorKind::Other, format!("no IP addresses found for {}", server))
        })?;
        Ok(ImapConnectFuture::TcpConnecting(TcpStream::connect(&addr), server.to_string()))
    }

    pub fn call(self, cmd: Command) -> ResponseStream {
        let Self { transport, mut state } = self;
        let request_id = state.request_ids.next().unwrap(); // safe: never returns Err
        let (cmd_bytes, next_state) = cmd.into_parts();
        let future = transport.send(Request(request_id.clone(), cmd_bytes));
        ResponseStream::new(future, state, request_id, next_state)
    }
}

pub struct ResponseStream {
    future: Option<Send<ImapTransport>>,
    transport: Option<ImapTransport>,
    state: Option<ClientState>,
    request_id: RequestId,
    next_state: Option<State>,
    done: bool,
}

impl ResponseStream {
    pub fn new(future: Send<ImapTransport>, state: ClientState,
               request_id: RequestId, next_state: Option<State>) -> Self {
        Self {
            future: Some(future),
            transport: None,
            state: Some(state),
            request_id: request_id,
            next_state: next_state,
            done: false,
        }
    }
}

impl StateStream for ResponseStream {
    type Item = ResponseData;
    type State = Client;
    type Error = io::Error;
    fn poll(&mut self) -> Poll<StreamEvent<Self::Item, Self::State>, Self::Error> {
        match self.future.take() {
            Some(mut future) => match future.poll() {
                Ok(Async::Ready(transport)) => {
                    self.transport = Some(transport);
                },
                Ok(Async::NotReady) => {
                    self.future = Some(future);
                    return Ok(Async::NotReady);
                },
                Err(e) => {
                    return Err(e);
                },
            },
            None => {},
        }
        if !self.transport.is_some() {
            return Ok(Async::NotReady);
        }
        let mut transport = self.transport.take().unwrap();
        if self.done {
            let mut state = self.state.take().unwrap();
            if self.next_state.is_some() {
                state.state = self.next_state.take().unwrap();
            }
            let client = Client { transport, state };
            return Ok(Async::Ready(StreamEvent::Done(client)));
        }
        match transport.poll() {
            Ok(Async::Ready(Some(rsp))) => {
                if let Some(req_id) = rsp.request_id() {
                    self.done = *req_id == self.request_id;
                };
                self.transport = Some(transport);
                return Ok(Async::Ready(StreamEvent::Next(rsp)));
            },
            Err(e) => {
                return Err(e);
            },
            _ => (),
        }
        self.transport = Some(transport);
        Ok(Async::NotReady)
    }
}

pub enum ImapConnectFuture {
    #[doc(hidden)] TcpConnecting(ConnectFuture, String),
    #[doc(hidden)] TlsHandshake(ConnectAsync<TcpStream>),
    #[doc(hidden)] ServerGreeting(Option<ImapTransport>),
}

impl Future for ImapConnectFuture {
    type Item = (Client, ResponseData);
    type Error = io::Error;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let mut new = None;
        if let ImapConnectFuture::TcpConnecting(ref mut future, ref domain) = *self {
            let stream = try_ready!(future.poll());
            let ctx = TlsConnector::builder().unwrap().build().unwrap();
            let future = ctx.connect_async(domain, stream);
            new = Some(ImapConnectFuture::TlsHandshake(future));
        }
        if new.is_some() {
            *self = new.take().unwrap();
        }
        if let ImapConnectFuture::TlsHandshake(ref mut future) = *self {
            let transport = try_ready!(future.map_err(|e| {
                io::Error::new(io::ErrorKind::Other, e)
            }).poll()).framed(ImapCodec::default());
            new = Some(ImapConnectFuture::ServerGreeting(Some(transport)));
        }
        if new.is_some() {
            *self = new.take().unwrap();
        }
        if let ImapConnectFuture::ServerGreeting(ref mut wrapped) = *self {
            let msg = try_ready!(wrapped.as_mut().unwrap().poll()).unwrap();
            return Ok(Async::Ready((Client {
                transport: wrapped.take().unwrap(),
                state: ClientState::new(),
            }, msg)));
        }
        Ok(Async::NotReady)
    }
}

pub struct ClientState {
    state: State,
    request_ids: IdGenerator,
}

impl ClientState {
    pub fn new() -> Self {
        Self {
            state: State::NotAuthenticated,
            request_ids: IdGenerator::new(),
        }
    }
}

impl Default for ClientState {
    fn default() -> Self {
        Self::new()
    }
}

pub struct IdGenerator {
    next: u64,
}

impl IdGenerator {
    pub fn new() -> Self {
        Self { next: 0 }
    }
}

impl Default for IdGenerator {
    fn default() -> Self {
        Self::new()
    }
}

impl Iterator for IdGenerator {
    type Item = RequestId;
    fn next(&mut self) -> Option<Self::Item> {
        self.next += 1;
        Some(RequestId(format!("A{:04}", self.next % 10_000)))
    }
}
<commit_msg>Use pattern matching for ResponseStream transport extraction<commit_after>use futures::{Async, Future, Poll, Sink};
use futures::stream::Stream;
use futures::sink::Send;
use futures_state_stream::{StateStream, StreamEvent};

use native_tls::TlsConnector;

use std::io;
use std::net::ToSocketAddrs;

use tokio::net::{ConnectFuture, TcpStream};
use tokio_io::AsyncRead;
use tokio_tls::{ConnectAsync, TlsConnectorExt};

use imap_proto::{Request, RequestId, State};
use imap_proto::builders::command::Command;
use proto::{ImapCodec, ImapTransport, ResponseData};

pub mod builder {
    pub use imap_proto::builders::command::{CommandBuilder, FetchBuilderAttributes,
                                            FetchBuilderMessages, FetchBuilderModifiers,
                                            FetchCommand, FetchCommandAttributes,
                                            FetchCommandMessages};
}

pub struct Client {
    transport: ImapTransport,
    state: ClientState,
}

impl Client {
    pub fn connect(server: &str) -> io::Result<ImapConnectFuture> {
        let addr = (server, 993).to_socket_addrs()?.next().ok_or_else(|| {
            io::Error::new(io::ErrorKind::Other, format!("no IP addresses found for {}", server))
        })?;
        Ok(ImapConnectFuture::TcpConnecting(TcpStream::connect(&addr), server.to_string()))
    }

    pub fn call(self, cmd: Command) -> ResponseStream {
        let Self { transport, mut state } = self;
        let request_id = state.request_ids.next().unwrap(); // safe: never returns Err
        let (cmd_bytes, next_state) = cmd.into_parts();
        let future = transport.send(Request(request_id.clone(), cmd_bytes));
        ResponseStream::new(future, state, request_id, next_state)
    }
}

pub struct ResponseStream {
    future: Option<Send<ImapTransport>>,
    transport: Option<ImapTransport>,
    state: Option<ClientState>,
    request_id: RequestId,
    next_state: Option<State>,
    done: bool,
}

impl ResponseStream {
    pub fn new(future: Send<ImapTransport>, state: ClientState,
               request_id: RequestId, next_state: Option<State>) -> Self {
        Self {
            future: Some(future),
            transport: None,
            state: Some(state),
            request_id: request_id,
            next_state: next_state,
            done: false,
        }
    }
}

impl StateStream for ResponseStream {
    type Item = ResponseData;
    type State = Client;
    type Error = io::Error;
    fn poll(&mut self) -> Poll<StreamEvent<Self::Item, Self::State>, Self::Error> {
        match self.future.take() {
            Some(mut future) => match future.poll() {
                Ok(Async::Ready(transport)) => {
                    self.transport = Some(transport);
                },
                Ok(Async::NotReady) => {
                    self.future = Some(future);
                    return Ok(Async::NotReady);
                },
                Err(e) => {
                    return Err(e);
                },
            },
            None => {},
        }
        let mut transport = match self.transport.take() {
            None => return Ok(Async::NotReady),
            Some(mut transport) => transport,
        };
        if self.done {
            let mut state = self.state.take().unwrap();
            if self.next_state.is_some() {
                state.state = self.next_state.take().unwrap();
            }
            let client = Client { transport, state };
            return Ok(Async::Ready(StreamEvent::Done(client)));
        }
        match transport.poll() {
            Ok(Async::Ready(Some(rsp))) => {
                if let Some(req_id) = rsp.request_id() {
                    self.done = *req_id == self.request_id;
                };
                self.transport = Some(transport);
                return Ok(Async::Ready(StreamEvent::Next(rsp)));
            },
            Err(e) => {
                return Err(e);
            },
            _ => (),
        }
        self.transport = Some(transport);
        Ok(Async::NotReady)
    }
}

pub enum ImapConnectFuture {
    #[doc(hidden)] TcpConnecting(ConnectFuture, String),
    #[doc(hidden)] TlsHandshake(ConnectAsync<TcpStream>),
    #[doc(hidden)] ServerGreeting(Option<ImapTransport>),
}

impl Future for ImapConnectFuture {
    type Item = (Client, ResponseData);
    type Error = io::Error;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let mut new = None;
        if let ImapConnectFuture::TcpConnecting(ref mut future, ref domain) = *self {
            let stream = try_ready!(future.poll());
            let ctx = TlsConnector::builder().unwrap().build().unwrap();
            let future = ctx.connect_async(domain, stream);
            new = Some(ImapConnectFuture::TlsHandshake(future));
        }
        if new.is_some() {
            *self = new.take().unwrap();
        }
        if let ImapConnectFuture::TlsHandshake(ref mut future) = *self {
            let transport = try_ready!(future.map_err(|e| {
                io::Error::new(io::ErrorKind::Other, e)
            }).poll()).framed(ImapCodec::default());
            new = Some(ImapConnectFuture::ServerGreeting(Some(transport)));
        }
        if new.is_some() {
            *self = new.take().unwrap();
        }
        if let ImapConnectFuture::ServerGreeting(ref mut wrapped) = *self {
            let msg = try_ready!(wrapped.as_mut().unwrap().poll()).unwrap();
            return Ok(Async::Ready((Client {
                transport: wrapped.take().unwrap(),
                state: ClientState::new(),
            }, msg)));
        }
        Ok(Async::NotReady)
    }
}

pub struct ClientState {
    state: State,
    request_ids: IdGenerator,
}

impl ClientState {
    pub fn new() -> Self {
        Self {
            state: State::NotAuthenticated,
            request_ids: IdGenerator::new(),
        }
    }
}

impl Default for ClientState {
    fn default() -> Self {
        Self::new()
    }
}

pub struct IdGenerator {
    next: u64,
}

impl IdGenerator {
    pub fn new() -> Self {
        Self { next: 0 }
    }
}

impl Default for IdGenerator {
    fn default() -> Self {
        Self::new()
    }
}

impl Iterator for IdGenerator {
    type Item = RequestId;
    fn next(&mut self) -> Option<Self::Item> {
        self.next += 1;
        Some(RequestId(format!("A{:04}", self.next % 10_000)))
    }
}
<|endoftext|>