<commit_before>// xfail-stage0

use std;
import std::either::*;
import std::vec::len;

fn test_either_left() {
  auto val = left(10);
  fn f_left(&int x) -> bool { x == 10 }
  fn f_right(&uint x) -> bool { false }
  assert (either(f_left, f_right, val));
}

fn test_either_right() {
  auto val = right(10u);
  fn f_left(&int x) -> bool { false }
  fn f_right(&uint x) -> bool { x == 10u }
  assert (either(f_left, f_right, val));
}

fn test_lefts() {
  auto input = [left(10),
                right(11),
                left(12),
                right(13),
                left(14)];
  auto result = lefts(input);
  assert (result == [10, 12, 14]);
}

fn test_lefts_none() {
  let vec[t[int, int]] input = [right(10),
                                right(10)];
  auto result = lefts(input);
  assert (len(result) == 0u);
}

fn test_lefts_empty() {
  let vec[t[int, int]] input = [];
  auto result = lefts(input);
  assert (len(result) == 0u);
}

fn test_rights() {
  auto input = [left(10),
                right(11),
                left(12),
                right(13),
                left(14)];
  auto result = rights(input);
  assert (result == [11, 13]);
}

fn test_rights_none() {
  let vec[t[int, int]] input = [left(10),
                                left(10)];
  auto result = rights(input);
  assert (len(result) == 0u);
}

fn test_rights_empty() {
    let vec[t[int, int]] input = [];
    auto result = rights(input);
    assert (len(result) == 0u);
}

fn test_partition() {
  auto input = [left(10),
                right(11),
                left(12),
                right(13),
                left(14)];
  auto result = partition(input);
  assert (result._0.(0) == 10);
  assert (result._0.(1) == 12);
  assert (result._0.(2) == 14);
  assert (result._1.(0) == 11);
  assert (result._1.(1) == 13);
}

fn test_partition_no_lefts() {
  let vec[t[int, int]] input = [right(10),
                                right(11)];
  auto result = partition(input);
  assert (len(result._0) == 0u);
  assert (len(result._1) == 2u);
}

fn test_partition_no_rights() {
  let vec[t[int, int]] input = [left(10),
                                left(11)];
  auto result = partition(input);
  assert (len(result._0) == 2u);
  assert (len(result._1) == 0u);
}

fn test_partition_empty() {
  let vec[t[int, int]] input = [];
  auto result = partition(input);
  assert (len(result._0) == 0u);
  assert (len(result._1) == 0u);
}

fn main() {
  test_either_left();
  test_either_right();
  test_lefts();
  test_lefts_none();
  test_lefts_empty();
  test_rights();
  test_rights_none();
  test_rights_empty();
  test_partition();
  test_partition_no_lefts();
  test_partition_no_rights();
  test_partition_empty();
}<commit_msg>test: Switch lib-either over to interior vectors. Puts out burning tinderbox.<commit_after>// xfail-stage0

use std;
import std::either::*;
import std::ivec::len;

fn test_either_left() {
  auto val = left(10);
  fn f_left(&int x) -> bool { x == 10 }
  fn f_right(&uint x) -> bool { false }
  assert (either(f_left, f_right, val));
}

fn test_either_right() {
  auto val = right(10u);
  fn f_left(&int x) -> bool { false }
  fn f_right(&uint x) -> bool { x == 10u }
  assert (either(f_left, f_right, val));
}

fn test_lefts() {
  auto input = ~[left(10),
                 right(11),
                 left(12),
                 right(13),
                 left(14)];
  auto result = lefts(input);
  assert (result == ~[10, 12, 14]);
}

fn test_lefts_none() {
  let (t[int, int])[] input = ~[right(10),
                                right(10)];
  auto result = lefts(input);
  assert (len(result) == 0u);
}

fn test_lefts_empty() {
  let (t[int, int])[] input = ~[];
  auto result = lefts(input);
  assert (len(result) == 0u);
}

fn test_rights() {
  auto input = ~[left(10),
                 right(11),
                 left(12),
                 right(13),
                 left(14)];
  auto result = rights(input);
  assert (result == ~[11, 13]);
}

fn test_rights_none() {
  let (t[int, int])[] input = ~[left(10),
                                left(10)];
  auto result = rights(input);
  assert (len(result) == 0u);
}

fn test_rights_empty() {
    let (t[int, int])[] input = ~[];
    auto result = rights(input);
    assert (len(result) == 0u);
}

fn test_partition() {
  auto input = ~[left(10),
                 right(11),
                 left(12),
                 right(13),
                 left(14)];
  auto result = partition(input);
  assert (result._0.(0) == 10);
  assert (result._0.(1) == 12);
  assert (result._0.(2) == 14);
  assert (result._1.(0) == 11);
  assert (result._1.(1) == 13);
}

fn test_partition_no_lefts() {
  let (t[int, int])[] input = ~[right(10),
                                right(11)];
  auto result = partition(input);
  assert (len(result._0) == 0u);
  assert (len(result._1) == 2u);
}

fn test_partition_no_rights() {
  let (t[int, int])[] input = ~[left(10),
                                left(11)];
  auto result = partition(input);
  assert (len(result._0) == 2u);
  assert (len(result._1) == 0u);
}

fn test_partition_empty() {
  let (t[int, int])[] input = ~[];
  auto result = partition(input);
  assert (len(result._0) == 0u);
  assert (len(result._1) == 0u);
}

fn main() {
  test_either_left();
  test_either_right();
  test_lefts();
  test_lefts_none();
  test_lefts_empty();
  test_rights();
  test_rights_none();
  test_rights_empty();
  test_partition();
  test_partition_no_lefts();
  test_partition_no_rights();
  test_partition_empty();
}
<|endoftext|>


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

// GetLastError doesn't seem to work with stack switching

#[cfg(windows)]
mod kernel32 {
  extern "system" {
    pub fn SetLastError(err: uint);
    pub fn GetLastError() -> uint;
  }
}

#[cfg(windows)]
pub fn main() {
    unsafe {
        let expected = 1234u;
        kernel32::SetLastError(expected);
        let actual = kernel32::GetLastError();
        info!("actual = {}", actual);
        assert_eq!(expected, actual);
    }
}

#[cfg(target_os = "macos")]
#[cfg(target_os = "linux")]
#[cfg(target_os = "freebsd")]
pub fn main() { }
<commit_msg>android support added to test case<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// GetLastError doesn't seem to work with stack switching

#[cfg(windows)]
mod kernel32 {
  extern "system" {
    pub fn SetLastError(err: uint);
    pub fn GetLastError() -> uint;
  }
}

#[cfg(windows)]
pub fn main() {
    unsafe {
        let expected = 1234u;
        kernel32::SetLastError(expected);
        let actual = kernel32::GetLastError();
        info!("actual = {}", actual);
        assert_eq!(expected, actual);
    }
}

#[cfg(target_os = "macos")]
#[cfg(target_os = "linux")]
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "android")]
pub fn main() { }
<|endoftext|>


<commit_before>use js_types::js_type::{JsT, JsType};
use std::vec::Vec;
use std::collections::hash_set::HashSet;
use uuid::Uuid;

/// A graph node that stores a set of object UIDs, as well as a list of
/// pointers to nodes it can flow to.
/// A variable v is live on edge e if there is:
///     - a node n in the CFG s.t. use[n] contains v
///     - a directed path from e -> n s.t. for every statement s on the path,
///       def[s] does not contain v
#[derive(Clone)]
struct LivenessNode {
    defs: HashSet<Uuid>,
    uses: HashSet<Uuid>,
    ins: HashSet<Uuid>,
    outs: HashSet<Uuid>,
    succ: Vec<Box<LivenessNode>>,
    pred: Vec<Box<LivenessNode>>,
}

struct LivenessGraph {
    root: LivenessNode,
    nodes: Vec<LivenessNode>,
}

impl LivenessNode {
    fn new() -> LivenessNode {
        LivenessNode {
            defs: HashSet::new(),
            uses: HashSet::new(),
            ins: HashSet::new(),
            outs: HashSet::new(),
            succ: Vec::new(),
            pred: Vec::new(),
        }
    }

    fn node_flow(&mut self) {
        self.ins = self.uses.union(&self.outs.difference(&self.defs).cloned().collect())
                            .cloned().collect();

        self.outs = self.succ.clone().into_iter().flat_map(|succ| succ.ins).collect();
    }

    // TODO Given a list of AST instructions, parse out what UUIDs are used

}

pub struct StackFrame<'m> {
    members: Vec<&'m JsT>,
}

impl<'m> StackFrame<'m> {
    pub fn new() -> StackFrame<'m> {
        StackFrame { members: Vec::new(), }
    }

    pub fn alloc_ref(&mut self, refce: &'m mut JsT)  {
        self.members.push(refce);
    }
}
<commit_msg>Implement graph flow analysis<commit_after>use js_types::js_type::{JsT, JsType};
use std::vec::Vec;
use std::collections::hash_set::HashSet;
use std::collections::vec_deque::VecDeque;
use uuid::Uuid;

/// A graph node that stores a set of object UIDs, as well as a list of
/// pointers to nodes it can flow to.
/// A variable v is live on edge e if there is:
///     - a node n in the CFG s.t. use[n] contains v
///     - a directed path from e -> n s.t. for every statement s on the path,
///       def[s] does not contain v
#[derive(Clone)]
struct LivenessNode {
    defs: HashSet<Uuid>,
    uses: HashSet<Uuid>,
    ins: HashSet<Uuid>,
    outs: HashSet<Uuid>,
    succ: Vec<Box<LivenessNode>>,
    pred: Vec<Box<LivenessNode>>,
}

struct LivenessGraph {
    nodes: Vec<LivenessNode>,
}

impl LivenessNode {
    fn new() -> LivenessNode {
        LivenessNode {
            defs: HashSet::new(),
            uses: HashSet::new(),
            ins: HashSet::new(),
            outs: HashSet::new(),
            succ: Vec::new(),
            pred: Vec::new(),
        }
    }

    fn node_flow(&mut self) {
        self.ins = self.uses.union(&self.outs.difference(&self.defs).cloned().collect())
                            .cloned().collect();

        self.outs = self.succ.clone().into_iter().flat_map(|s| s.ins).collect();
    }

    // TODO Given a list of AST instructions, parse out what UUIDs are used

}

impl LivenessGraph {
    fn new() -> LivenessGraph {
        LivenessGraph {
            nodes: Vec::new(),
        }
    }

    fn graph_flow(&mut self) {
        let mut node_queue: VecDeque<&mut LivenessNode> = self.nodes.iter_mut().collect();
        while let Some(n) = node_queue.pop_front() {
            let old_ins = n.ins.clone();
            let old_outs = n.outs.clone();
            n.node_flow();
            if old_outs != n.outs {
                n.succ.iter_mut().map(|s| node_queue.push_back(s));
            }
        }
    }
}

pub struct StackFrame<'m> {
    members: Vec<&'m JsT>,
}

impl<'m> StackFrame<'m> {
    pub fn new() -> StackFrame<'m> {
        StackFrame { members: Vec::new(), }
    }

    pub fn alloc_ref(&mut self, refce: &'m mut JsT)  {
        self.members.push(refce);
    }
}
<|endoftext|>


<commit_before>use js_types::js_type::{JsT, JsType};
use std::vec::Vec;
use std::collections::hash_set::HashSet;
use std::collections::vec_deque::VecDeque;
use uuid::Uuid;

/// A graph node that stores a set of object UIDs, as well as a list of
/// pointers to nodes it can flow to.
/// A variable v is live on edge e if there is:
///     - a node n in the CFG s.t. use[n] contains v
///     - a directed path from e -> n s.t. for every statement s on the path,
///       def[s] does not contain v
#[derive(Clone)]
struct LivenessNode {
    defs: HashSet<Uuid>,
    uses: HashSet<Uuid>,
    ins: HashSet<Uuid>,
    outs: HashSet<Uuid>,
    succ: Vec<Box<LivenessNode>>,
    pred: Vec<Box<LivenessNode>>,
}

struct LivenessGraph {
    nodes: Vec<LivenessNode>,
}

type Statement = i32; // TODO, placeholder

impl LivenessNode {
    fn new() -> LivenessNode {
        LivenessNode {
            defs: HashSet::new(),
            uses: HashSet::new(),
            ins: HashSet::new(),
            outs: HashSet::new(),
            succ: Vec::new(),
            pred: Vec::new(),
        }
    }

    fn node_flow(&mut self) {
        self.ins = self.uses.union(&self.outs.difference(&self.defs).cloned().collect())
                            .cloned().collect();

        self.outs = self.succ.clone().into_iter().flat_map(|s| s.ins).collect();
    }

    // TODO Given a list of AST instructions, parse out what UUIDs are used
    fn compute_uses(&mut self, statements: Vec<Statement>) {

    }

    fn compute_defs(&mut self, statements: Vec<Statement>) {

    }

}

impl LivenessGraph {
    fn new() -> LivenessGraph {
        LivenessGraph {
            nodes: Vec::new(),
        }
    }

    fn graph_flow(&mut self) {
        let mut node_queue: VecDeque<&mut LivenessNode> = self.nodes.iter_mut().collect();
        while let Some(n) = node_queue.pop_front() {
            let old_ins = n.ins.clone();
            let old_outs = n.outs.clone();
            n.node_flow();
            if old_outs != n.outs {
                n.succ.iter_mut().map(|s| node_queue.push_back(s));
            }
        }
    }
}

pub struct StackFrame<'m> {
    members: Vec<&'m JsT>,
}

impl<'m> StackFrame<'m> {
    pub fn new() -> StackFrame<'m> {
        StackFrame { members: Vec::new(), }
    }

    pub fn alloc_ref(&mut self, refce: &'m mut JsT)  {
        self.members.push(refce);
    }
}
<commit_msg>Add UUID map for object IDs, but need to rework it to put it inside an arena<commit_after>use js_types::js_type::{JsT, JsType, Marking};
use std::vec::Vec;
use std::collections::hash_set::HashSet;
use std::collections::hash_map::HashMap;
use std::collections::vec_deque::VecDeque;
use uuid::Uuid;

/// A map from uuids to references to objects. The interface to the garbage
/// collector, this map gets updated whenever a GC cycle is performed. References
/// that are no longer live may be dropped from the map.
pub struct UuidMap<'t> {
    inner: HashMap<Uuid, RefCell<JsT>>,
}

impl<'t> UuidMap<'t> {
    pub fn new() -> UuidMap<'t> {
        UuidMap {
            inner: HashMap::new(),
        }
    }

    pub fn from_jsts(jsts: Vec<&'t JsT>) -> UuidMap<'t> {
        let mut tmp_map = HashMap::new();
        jsts.iter().map(|j| tmp_map.insert(j.uuid, *j));
        UuidMap {
            inner: tmp_map,
        }
    }

    pub fn insert_ref(&mut self, jst: &'t JsT) {
        self.inner.insert(jst.uuid, jst);
    }

    pub fn drop_uuid(&mut self, uuid: Uuid) {
        self.inner.remove(&uuid);
    }

    pub fn drop_ref(&mut self, jst: &'t JsT) {
        self.inner.remove(&jst.uuid);
    }

    pub fn mark_uuid(&mut self, uuid: Uuid, marking: Marking) {
        if let Some(jst) = self.inner.get_mut(&uuid) {
            (*jst).gc_flag = marking;
        }
        //let jst_opt = self.inner.get_mut(&uuid);
        //if let Some(jst) = jst_opt {
        //    let ref mut jst = jst.clone();
        //    jst.gc_flag = marking;
        //    self.inner.insert(uuid, jst);
        //}
    }
}

/// A graph node that stores sets of object uuids, as well as a list of
/// pointers to nodes it can flow to.
/// A variable v is live on edge e if there is:
///     - a node n in the CFG s.t. use[n] contains v
///     - a directed path from e -> n s.t. for every statement s on the path,
///       def[s] does not contain v
#[derive(Clone)]
struct LivenessNode {
    defs: HashSet<Uuid>,
    uses: HashSet<Uuid>,
    ins: HashSet<Uuid>,
    outs: HashSet<Uuid>,
    succ: Vec<Box<LivenessNode>>,
    pred: Vec<Box<LivenessNode>>,
}

struct LivenessGraph {
    nodes: Vec<LivenessNode>,
}

type Statement = i32; // TODO, placeholder

impl LivenessNode {
    fn new() -> LivenessNode {
        LivenessNode {
            defs: HashSet::new(),
            uses: HashSet::new(),
            ins: HashSet::new(),
            outs: HashSet::new(),
            succ: Vec::new(),
            pred: Vec::new(),
        }
    }

    fn node_flow(&mut self) {
        self.ins = self.uses.union(&self.outs.difference(&self.defs).cloned().collect())
                            .cloned().collect();

        self.outs = self.succ.clone().into_iter().flat_map(|s| s.ins).collect();
    }

    // TODO Given a list of AST instructions, parse out what UUIDs are used
    fn compute_uses(&mut self, statements: Vec<Statement>) {

    }

    fn compute_defs(&mut self, statements: Vec<Statement>) {

    }

}

impl LivenessGraph {
    fn new() -> LivenessGraph {
        LivenessGraph {
            nodes: Vec::new(),
        }
    }

    fn graph_flow(&mut self) {
        let mut node_queue: VecDeque<&mut LivenessNode> = self.nodes.iter_mut().collect();
        while let Some(n) = node_queue.pop_front() {
            let old_ins = n.ins.clone();
            let old_outs = n.outs.clone();
            n.node_flow();
            if old_outs != n.outs {
                n.succ.iter_mut().map(|s| node_queue.push_back(s));
            }
        }
    }
}

pub struct StackFrame<'m> {
    members: Vec<&'m JsT>,
}

impl<'m> StackFrame<'m> {
    pub fn new() -> StackFrame<'m> {
        StackFrame { members: Vec::new(), }
    }

    pub fn alloc_ref(&mut self, refce: &'m mut JsT)  {
        self.members.push(refce);
    }
}
<|endoftext|>


<commit_before>use std::str::from_utf8;

use rustc_serialize::*;

use websocket::Message;
use websocket::Sender as WebSocketSender;
use websocket::Receiver as WebSocketReceiver;
use websocket::message::Type;
use websocket::Client;
use websocket::client::request::Url;
use websocket::result::WebSocketError;

use payment_detection::{PaymentDetection, PaymentError};

#[derive(RustcDecodable)]
pub struct AddressEvent {
	pub op: String,
	pub x: Transaction,
}

#[derive(RustcDecodable)]
pub struct Transaction {
	pub hash: String,
	pub ver: u8,
	pub vin_sz: u8,
	pub vout_sz: u8,
	pub lock_time: u64,
	pub size: u64,
	pub relayed_by: String,
	pub tx_index: u64,
	pub time: u64,
	pub inputs: Vec<TransactionInput>,
	pub out: Vec<TransactionOutput>
}

#[derive(RustcDecodable)]
pub struct TransactionOutput {
	pub value: u64,
	//pub type_: u8, too lazy to write a custom decoder just because "type" appears to be a rust keyword
	pub addr: String,
	pub tx_index: u64,
	pub spent: bool,
	pub n: u32,
	pub script: String,
}

#[derive(RustcDecodable)]
pub struct TransactionInput {
	pub prev_out: TransactionOutput,
	pub sequence: u64,
	pub script: String
}

#[derive(RustcEncodable)]
pub struct AddressSubscription<'a> {
	op: &'a str,
	addr: &'a str
}

const ADDRESS_SUBCRIPTION_OP: &'static str = "addr_sub";

impl<'a> AddressSubscription<'a> {
	pub fn new(address: &str) -> AddressSubscription {
		AddressSubscription {
			op: ADDRESS_SUBCRIPTION_OP,
			addr: address
		}
	}
}

pub struct BlockchainInfo<'a> {
	websocket_url: String,
	websocket_msg: String,
	address: &'a str,
	amount: u64
}

const WEBSOCKET_URL: &'static str = "wss://ws.blockchain.info/inv";

impl<'a> PaymentDetection<'a> for BlockchainInfo<'a> {
	fn new(address: &'a str, amount: u64) -> Self {
		let address_subscription = AddressSubscription::new(address);
		let json_request = json::encode(&address_subscription).unwrap();

		BlockchainInfo {
			websocket_url: WEBSOCKET_URL.to_string(),
			websocket_msg: json_request,
			address: &address,
			amount: amount
		}
	}

	fn wait(&self) -> Result<(), PaymentError> {
		let websocket_url = Url::parse(&self.websocket_url).unwrap();
		println!("Connecting to {}", websocket_url);

		let request = Client::connect(websocket_url).unwrap();

		let response = request.send().unwrap(); // Send the request and retrieve a response

		let mut client = response.begin(); // Get a Client

		println!("Successfully connected");

		client.send_message(&Message::text(self.websocket_msg.to_string())).unwrap(); // Send message

		let mut amount_sum = 0;
		for message in client.incoming_messages() {
		    let message: Message = match message {
		    	Ok(m) => m,
		    	Err(e) => match e as WebSocketError {
		    		WebSocketError::NoDataAvailable => return Err(PaymentError::Timeout),
		    		_ => return Err(PaymentError::BackendError)
		    	}
		    };

			match message.opcode {
				Type::Text => {
					match incoming_amount(&*message.payload, &self.address.to_string()) {
						Ok(amount) => {
							amount_sum = amount_sum + amount;
							if amount_sum >= self.amount {
								println!("PAYMENT COMPLETE");
								break;
							}
						},
						Err(e) => return Err(e)
					}
				}

				Type::Close => {
					if amount_sum > 0 {
						return Err(PaymentError::InsufficientAmount);
					} else {
					    return Err(PaymentError::Timeout);
					}
				}

				_ => {
					println!("Backend error (unhandled websocket message): {:?}", message);
					return Err(PaymentError::BackendError);
				}
			}
		}

		Ok(())
	}
}

fn incoming_amount(data: &[u8], address: &str) -> Result<u64, PaymentError> {
	let data = match from_utf8(data) {
        Ok(v) => v,
        Err(e) => {
        	println!("Backend error (UTF-8 decoding): {:?}", e);
        	return Err(PaymentError::BackendError);
        }
    };

	let address_event: AddressEvent = match json::decode(&data) {
		Ok(ae) => ae,
		Err(e) => {
			println!("Backend error (JSON decoding): {:?}", e);
			return Err(PaymentError::BackendError);
		}
	};

	let transaction: Transaction = address_event.x;

	let mut amount_payed = 0;
	for output in &transaction.out {
		if output.addr == address {
			println!("received {} satoshis from {}", output.value, &transaction.inputs[0].prev_out.addr);
			amount_payed = amount_payed + output.value;
		}
	}

	Ok(amount_payed)
}

<commit_msg>removed unused fields from blockchain.info response description of address subscription<commit_after>use std::str::from_utf8;

use rustc_serialize::*;

use websocket::Message;
use websocket::Sender as WebSocketSender;
use websocket::Receiver as WebSocketReceiver;
use websocket::message::Type;
use websocket::Client;
use websocket::client::request::Url;
use websocket::result::WebSocketError;

use payment_detection::{PaymentDetection, PaymentError};

// For complete blockchain.info API see: https://blockchain.info/de/api/api_websocket

#[derive(RustcDecodable)]
pub struct AddressEvent {
	pub x: Transaction,
}

#[derive(RustcDecodable)]
pub struct Transaction {
	pub inputs: Vec<TransactionInput>,
	pub out: Vec<TransactionOutput>
}

#[derive(RustcDecodable)]
pub struct TransactionOutput {
	pub value: u64,
	pub addr: String,
}

#[derive(RustcDecodable)]
pub struct TransactionInput {
	pub prev_out: TransactionOutput,
}

#[derive(RustcEncodable)]
pub struct AddressSubscription<'a> {
	op: &'a str,
	addr: &'a str
}

const ADDRESS_SUBCRIPTION_OP: &'static str = "addr_sub";

impl<'a> AddressSubscription<'a> {
	pub fn new(address: &str) -> AddressSubscription {
		AddressSubscription {
			op: ADDRESS_SUBCRIPTION_OP,
			addr: address
		}
	}
}

pub struct BlockchainInfo<'a> {
	websocket_url: String,
	websocket_msg: String,
	address: &'a str,
	amount: u64
}

const WEBSOCKET_URL: &'static str = "wss://ws.blockchain.info/inv";

impl<'a> PaymentDetection<'a> for BlockchainInfo<'a> {
	fn new(address: &'a str, amount: u64) -> Self {
		let address_subscription = AddressSubscription::new(address);
		let json_request = json::encode(&address_subscription).unwrap();

		BlockchainInfo {
			websocket_url: WEBSOCKET_URL.to_string(),
			websocket_msg: json_request,
			address: &address,
			amount: amount
		}
	}

	fn wait(&self) -> Result<(), PaymentError> {
		let websocket_url = Url::parse(&self.websocket_url).unwrap();
		println!("Connecting to {}", websocket_url);

		let request = Client::connect(websocket_url).unwrap();

		let response = request.send().unwrap(); // Send the request and retrieve a response

		let mut client = response.begin(); // Get a Client

		println!("Successfully connected");

		client.send_message(&Message::text(self.websocket_msg.to_string())).unwrap(); // Send message

		let mut amount_sum = 0;
		for message in client.incoming_messages() {
		    let message: Message = match message {
		    	Ok(m) => m,
		    	Err(e) => match e as WebSocketError {
		    		WebSocketError::NoDataAvailable => return Err(PaymentError::Timeout),
		    		_ => return Err(PaymentError::BackendError)
		    	}
		    };

			match message.opcode {
				Type::Text => {
					match incoming_amount(&*message.payload, &self.address.to_string()) {
						Ok(amount) => {
							amount_sum = amount_sum + amount;
							if amount_sum >= self.amount {
								println!("PAYMENT COMPLETE");
								break;
							}
						},
						Err(e) => return Err(e)
					}
				}

				Type::Close => {
					if amount_sum > 0 {
						return Err(PaymentError::InsufficientAmount);
					} else {
					    return Err(PaymentError::Timeout);
					}
				}

				_ => {
					println!("Backend error (unhandled websocket message): {:?}", message);
					return Err(PaymentError::BackendError);
				}
			}
		}

		Ok(())
	}
}

fn incoming_amount(data: &[u8], address: &str) -> Result<u64, PaymentError> {
	let data = match from_utf8(data) {
        Ok(v) => v,
        Err(e) => {
        	println!("Backend error (UTF-8 decoding): {:?}", e);
        	return Err(PaymentError::BackendError);
        }
    };

	let address_event: AddressEvent = match json::decode(&data) {
		Ok(ae) => ae,
		Err(e) => {
			println!("Backend error (JSON decoding): {:?}", e);
			return Err(PaymentError::BackendError);
		}
	};

	let transaction: Transaction = address_event.x;

	let mut amount_payed = 0;
	for output in &transaction.out {
		if output.addr == address {
			println!("received {} satoshis from {}", output.value, &transaction.inputs[0].prev_out.addr);
			amount_payed = amount_payed + output.value;
		}
	}

	Ok(amount_payed)
}

<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::mem;

use llvm_sys::{core, LLVMIntPredicate, LLVMRealPredicate};
use llvm_sys::prelude::{
  LLVMBuilderRef,
  LLVMValueRef
};
use libc::{c_char, c_uint};

use types::Ty;
use block::BasicBlock;
use value::{Function, Value, ValueRef, Predicate, PhiNode};

static NULL_NAME:[c_char; 1] = [0];

pub struct Builder(pub LLVMBuilderRef);
impl_dispose!(Builder, core::LLVMDisposeBuilder);

macro_rules! unary_op (
  ($name:ident, $func:ident) => (
    pub fn $name(&self, value: &Value) -> Value {
      Value(unsafe {
        core::$func(self.0, value.into(), NULL_NAME.as_ptr() as *const c_char)
      })
    }
  );
);

impl Builder {

  pub fn get_insert_block(&self) -> BasicBlock
  {
    BasicBlock(unsafe { core::LLVMGetInsertBlock(self.0)})
  }

  /// Position the builder at `instr` within `block`.
  pub fn position_at(&self, block: &BasicBlock, instr: &Value)
  {
    unsafe { core::LLVMPositionBuilder(self.0, block.0, instr.0) }
  }

  /// Position the builder at the end of `block`.
  pub fn position_at_end(&self, block: &BasicBlock)
  {
    unsafe { core::LLVMPositionBuilderAtEnd(self.0, block.0) }
  }

  /// Build an instruction that returns from the function with void.
  pub fn create_ret_void(&self) -> Value
  {
    Value(unsafe {core::LLVMBuildRetVoid(self.0)})
  }

  /// Build an instruction that returns from the function with `value`.
  pub fn create_ret(&self, value: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildRet(self.0, value.0)})
  }

  /// Build an instruction that allocates an array with the element type `elem` and
  /// the size `size`.
  ///
  /// The size of this array will be the size of `elem` times `size`.
  pub fn build_array_alloca(&self, elem: &Ty, size: &Value) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildArrayAlloca(self.0,
    														 elem.0,
    														 size.0,
    														 NULL_NAME.as_ptr() as *const c_char)
    })
  }

  /// Build an instruction that allocates a pointer to fit the size of `ty` then returns this
  /// pointer.
  ///
  /// Make sure to call `build_free` with the pointer value when you're done with it, or you're
  /// gonna have a bad time.
  pub fn create_alloca(&self, ty: &Ty) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildAlloca(self.0,
    												ty.0,
    												NULL_NAME.as_ptr() as *const c_char)
    })
  }

  /// Build an instruction that frees the `val`, which _MUST_ be a pointer that was returned
  /// from `build_alloca`.
  pub fn create_free(&self, val: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildFree(self.0, val.0) })
  }

  /// Build an instruction that store the value `val` in the pointer `ptr`.
  pub fn create_store(&self, val: &Value, ptr: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildStore(self.0, val.0, ptr.0) })
  }

  /// Build an instruction that branches to the block `dest`.
  pub fn create_br(&self, dest: &BasicBlock) -> Value
  {
    Value(unsafe { core::LLVMBuildBr(self.0, dest.0)})
  }

  /// Build an instruction that branches to `if_block` if `cond` evaluates to true, and
  /// `else_block` otherwise.
  pub fn create_cond_br(&self, cond: &Value,
  	                    if_block: &BasicBlock, else_block: &BasicBlock) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildCondBr(self.0,
    		                    cond.0,
    		                    if_block.0,
    		                    mem::transmute(else_block.0))
    })
  }

  /// Build an instruction that runs whichever block matches the value, or `default` if none of
  /// them matched it.
  pub fn create_switch(&self,
  	                   value: &Value,
  	                   default: &BasicBlock,
  	                   cases: &[(&Value, &BasicBlock)]) -> Value {
    Value(unsafe {
      let switch = core::LLVMBuildSwitch(self.0,
      	                                 value.0,
      	                                 default.0,
        	                                 cases.len() as c_uint);
      for case in cases {
        core::LLVMAddCase(switch, (case.0).0, (case.1).0);
      }

      switch
    })
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  fn create_call_internal(&self, func: &Function, args: &[&Value], tail_call: bool) -> Value
  {
    let ref_array = to_llvmref_array!(args, LLVMValueRef);

    Value(unsafe {
        let call = core::LLVMBuildCall(self.0,
        	                             func.0,
                                       ref_array.as_ptr() as *mut LLVMValueRef,
        	                             args.len() as c_uint,
        	                             NULL_NAME.as_ptr());
        core::LLVMSetTailCall(call, if tail_call {1} else {0});
        call.into()
    })
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  pub fn create_call(&self, func: &Function, args: &[&Value]) -> Value
  {
    self.create_call_internal(func, args, false)
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  pub fn create_tail_call(&self, func: &Function, args: &[&Value]) -> Value
  {
    self.create_call_internal(func, args, true)
  }

  /// Build an instruction that yields to `true_val` if `cond` is equal to `1`, and `false_val`
  /// otherwise.
  pub fn create_select(&self, cond: &Value, true_val: &Value, false_val: &Value) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildSelect(self.0,
    		                    cond.0,
    		                    true_val.0,
    		                    false_val.0,
    		                    NULL_NAME.as_ptr()) })
  }

  /// Build an instruction that casts a value into a certain type.
  pub fn create_bit_cast(&self, value: &Value, dest: &Ty) -> Value
  {
    Value(unsafe { core::LLVMBuildBitCast(
    		self.0,
    		value.0,
    		dest.0,
    		NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction that inserts a value into an aggregate data value.
  pub fn create_insert_value(&self, agg: &Value, elem: &Value, index: usize) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildInsertValue(self.0,
    		                         agg.0,
    		                         elem.0,
    		                         index as c_uint,
    		                         NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction that extracts a value from an aggregate type.
	pub fn create_extract_value(&self, agg: &Value, index: usize) -> Value {
    Value(unsafe {
    	core::LLVMBuildExtractValue(self.0,
    		                          agg.0,
    		                          index as c_uint,
    		                          NULL_NAME.as_ptr())
   	})
  }

  unary_op!{create_load, LLVMBuildLoad}

  /// Build an instruction to compare two values with the predicate given.
  pub fn create_cmp(&self, l: &Value, r: &Value, pred: Predicate) -> Value
  {
    self.create_cmp_internal(l, r, pred, true)
  }

  /// Build an instruction to compare two values with the predicate given.
  pub fn create_ucmp(&self, l: &Value, r: &Value, pred: Predicate) -> Value
  {
    self.create_cmp_internal(l, r, pred, false)
  }

  fn create_cmp_internal(&self, l: &Value, r: &Value,
  											 pred: Predicate, signed: bool) -> Value {
  	let (lhs_ty, rhs_ty) = (l.ty(), r.ty());
    assert_eq!(lhs_ty, rhs_ty);

    if lhs_ty.is_integer() {
	    let p = match (pred, signed) {
	    	(Predicate::Eq,    _)   => LLVMIntPredicate::LLVMIntEQ,
	    	(Predicate::NotEq, _)   => LLVMIntPredicate::LLVMIntNE,
	    	(Predicate::Lth, true)  => LLVMIntPredicate::LLVMIntSLT,
	    	(Predicate::Lth, false) => LLVMIntPredicate::LLVMIntULT,
	    	(Predicate::Leq, true)  => LLVMIntPredicate::LLVMIntSLE,
	    	(Predicate::Leq, false) => LLVMIntPredicate::LLVMIntULE,
	    	(Predicate::Gth, true)  => LLVMIntPredicate::LLVMIntSGT,
	    	(Predicate::Gth, false) => LLVMIntPredicate::LLVMIntUGT,
	    	(Predicate::Geq, true)  => LLVMIntPredicate::LLVMIntSGE,
	    	(Predicate::Geq, false) => LLVMIntPredicate::LLVMIntUGE,
	    };

	    Value(unsafe {
		    core::LLVMBuildICmp(self.0,
	    		                  p,
	     		                  l.0, r.0,
	     		                  NULL_NAME.as_ptr())
	    })

    } else if lhs_ty.is_float() {
    	let p = match pred {
        Predicate::Eq    => LLVMRealPredicate::LLVMRealOEQ,
        Predicate::NotEq => LLVMRealPredicate::LLVMRealONE,
        Predicate::Gth   => LLVMRealPredicate::LLVMRealOGT,
        Predicate::Geq   => LLVMRealPredicate::LLVMRealOGE,
        Predicate::Lth   => LLVMRealPredicate::LLVMRealOLT,
        Predicate::Leq   => LLVMRealPredicate::LLVMRealOLE
      };

   	  Value(unsafe {
      	core::LLVMBuildFCmp(self.0,
      		                 p, l.0, r.0,
      		                 NULL_NAME.as_ptr())
      })

    } else {
      panic!("expected numbers, got {:?}", lhs_ty)
    }
  }

  /// Build an instruction that computes the address of a subelement of an aggregate data
  /// structure.
  ///
  /// Basically type-safe pointer arithmetic.
  pub fn create_gep(&self, pointer: &Value, indices: &[&Value]) -> Value
  {
    let ref_array = to_llvmref_array!(indices, LLVMValueRef);

    Value(unsafe {
    	core::LLVMBuildInBoundsGEP(self.0,
    	                           pointer.0,
    	                           ref_array.as_ptr() as *mut LLVMValueRef,
    	                           indices.len() as c_uint,
    	                           NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction to select a value depending on the predecessor of the current block.
  pub fn create_phi(&self, ty: &Ty, name: &str) -> PhiNode
  {
	  PhiNode(unsafe {
	  	core::LLVMBuildPhi(self.0, ty.0, ::util::chars::from_str(name))
  	})
  }
}

#[cfg(test)]
mod tests {
	use super::*;
  use super::super::*;
  use types::LLVMTy;
  use value::{Predicate, ToValue};

	#[test]
	pub fn test_cond_br()
	{
		let jit = JitCompiler::new("test1").ok().unwrap();
    let ctx = jit.context();
    let module = jit.module();

    let func_ty = jit.create_func_ty(&u64::llvm_ty(ctx), &[&u64::llvm_ty(ctx)]);
    let func = jit.add_func("fib", &func_ty);
    let value = func.arg(0);

    let entry = func.append("entry");
    let then_bb = func.append("then_block");
    let else_bb = func.append("else_block");
    let merge_bb = func.append("merge_block");

    let builder = jit.builder();

    builder.position_at_end(&entry);
    let local = builder.create_alloca(&u64::llvm_ty(ctx));
    let cond = builder.create_cmp(&value.into(), &5u64.to_value(ctx), Predicate::Lth);
    builder.create_cond_br(&cond, &then_bb, &else_bb);

    builder.position_at_end(&then_bb);
    builder.create_store(&8u64.to_value(ctx), &local);
    builder.create_br(&merge_bb);

    builder.position_at_end(&else_bb);
    builder.create_store(&16u64.to_value(ctx), &local);
    builder.create_br(&merge_bb);

    builder.position_at_end(&merge_bb);
    let ret_val = builder.create_load(&local);
    builder.create_ret(&ret_val);

    jit.verify().unwrap();

    /*
    let ee = JitEngine::new(&module, JitOptions {opt_level: 0}).unwrap();
    ee.with_function(func, |fib: extern fn(u64) -> u64| {
      for i in 0..10 {
        if i < 5 {
          assert_eq!(8, fib(i));
        } else {
          assert_eq!(16, fib(i));
        }
      }
    });*/
	}
}<commit_msg>Add unary and binary instructor builder APIs and its macro.<commit_after>#![allow(dead_code)]

use std::mem;

use llvm_sys::{core, LLVMIntPredicate, LLVMRealPredicate};
use llvm_sys::prelude::{
  LLVMBuilderRef,
  LLVMValueRef
};
use libc::{c_char, c_uint};

use types::Ty;
use block::BasicBlock;
use value::{Function, Value, ValueRef, Predicate, PhiNode};

static NULL_NAME:[c_char; 1] = [0];

pub struct Builder(pub LLVMBuilderRef);
impl_dispose!(Builder, core::LLVMDisposeBuilder);

macro_rules! unary_instr (
  ($name:ident, $func:ident) => (
    pub fn $name(&self, value: &Value) -> Value {
      Value(unsafe {
        core::$func(self.0, value.0, NULL_NAME.as_ptr() as *const c_char)
      })
    }
  );
);

macro_rules! bin_instr (
  ($name:ident, $func:ident) => (
    pub fn $name(&self, lhs: &Value, rhs: &Value) -> Value
    {
      Value(unsafe {
        core::$func(self.0, lhs.0, rhs.0, NULL_NAME.as_ptr())
      })
    }
  );
  ($name:ident, $ifunc:ident, $ffunc:ident) => (
    pub fn $name(&self, lhs: &Value, rhs: &Value) -> Value {
      let lhs_ty = lhs.ty();
      let rhs_ty = rhs.ty();
      debug_assert_eq!(lhs_ty, rhs_ty);

      let instr_fn = if lhs_ty.is_integer() {
        core::$ifunc
      } else {
        core::$ffunc
      };

      Value(unsafe {
        instr_fn(self.0, lhs.0, rhs.0, NULL_NAME.as_ptr())
      })
    }
  );
);

impl Builder {

  pub fn get_insert_block(&self) -> BasicBlock
  {
    BasicBlock(unsafe { core::LLVMGetInsertBlock(self.0)})
  }

  /// Position the builder at `instr` within `block`.
  pub fn position_at(&self, block: &BasicBlock, instr: &Value)
  {
    unsafe { core::LLVMPositionBuilder(self.0, block.0, instr.0) }
  }

  /// Position the builder at the end of `block`.
  pub fn position_at_end(&self, block: &BasicBlock)
  {
    unsafe { core::LLVMPositionBuilderAtEnd(self.0, block.0) }
  }

  /// Build an instruction that returns from the function with void.
  pub fn create_ret_void(&self) -> Value
  {
    Value(unsafe {core::LLVMBuildRetVoid(self.0)})
  }

  /// Build an instruction that returns from the function with `value`.
  pub fn create_ret(&self, value: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildRet(self.0, value.0)})
  }

  /// Build an instruction that allocates an array with the element type `elem` and
  /// the size `size`.
  ///
  /// The size of this array will be the size of `elem` times `size`.
  pub fn build_array_alloca(&self, elem: &Ty, size: &Value) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildArrayAlloca(self.0,
    														 elem.0,
    														 size.0,
    														 NULL_NAME.as_ptr() as *const c_char)
    })
  }

  /// Build an instruction that allocates a pointer to fit the size of `ty` then returns this
  /// pointer.
  ///
  /// Make sure to call `build_free` with the pointer value when you're done with it, or you're
  /// gonna have a bad time.
  pub fn create_alloca(&self, ty: &Ty) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildAlloca(self.0,
    												ty.0,
    												NULL_NAME.as_ptr() as *const c_char)
    })
  }

  /// Build an instruction that frees the `val`, which _MUST_ be a pointer that was returned
  /// from `build_alloca`.
  pub fn create_free(&self, val: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildFree(self.0, val.0) })
  }

  /// Build an instruction that store the value `val` in the pointer `ptr`.
  pub fn create_store(&self, val: &Value, ptr: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildStore(self.0, val.0, ptr.0) })
  }

  /// Build an instruction that branches to the block `dest`.
  pub fn create_br(&self, dest: &BasicBlock) -> Value
  {
    Value(unsafe { core::LLVMBuildBr(self.0, dest.0)})
  }

  /// Build an instruction that branches to `if_block` if `cond` evaluates to true, and
  /// `else_block` otherwise.
  pub fn create_cond_br(&self, cond: &Value,
  	                    if_block: &BasicBlock, else_block: &BasicBlock) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildCondBr(self.0,
    		                    cond.0,
    		                    if_block.0,
    		                    mem::transmute(else_block.0))
    })
  }

  /// Build an instruction that runs whichever block matches the value, or `default` if none of
  /// them matched it.
  pub fn create_switch(&self,
  	                   value: &Value,
  	                   default: &BasicBlock,
  	                   cases: &[(&Value, &BasicBlock)]) -> Value {
    Value(unsafe {
      let switch = core::LLVMBuildSwitch(self.0,
      	                                 value.0,
      	                                 default.0,
        	                                 cases.len() as c_uint);
      for case in cases {
        core::LLVMAddCase(switch, (case.0).0, (case.1).0);
      }

      switch
    })
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  fn create_call_internal(&self, func: &Function, args: &[&Value], tail_call: bool) -> Value
  {
    let ref_array = to_llvmref_array!(args, LLVMValueRef);

    Value(unsafe {
        let call = core::LLVMBuildCall(self.0,
        	                             func.0,
                                       ref_array.as_ptr() as *mut LLVMValueRef,
        	                             args.len() as c_uint,
        	                             NULL_NAME.as_ptr());
        core::LLVMSetTailCall(call, if tail_call {1} else {0});
        call.into()
    })
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  pub fn create_call(&self, func: &Function, args: &[&Value]) -> Value
  {
    self.create_call_internal(func, args, false)
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  pub fn create_tail_call(&self, func: &Function, args: &[&Value]) -> Value
  {
    self.create_call_internal(func, args, true)
  }

  /// Build an instruction that yields to `true_val` if `cond` is equal to `1`, and `false_val`
  /// otherwise.
  pub fn create_select(&self, cond: &Value, true_val: &Value, false_val: &Value) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildSelect(self.0,
    		                    cond.0,
    		                    true_val.0,
    		                    false_val.0,
    		                    NULL_NAME.as_ptr()) })
  }

  /// Build an instruction that casts a value into a certain type.
  pub fn create_bit_cast(&self, value: &Value, dest: &Ty) -> Value
  {
    Value(unsafe { core::LLVMBuildBitCast(
    		self.0,
    		value.0,
    		dest.0,
    		NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction that inserts a value into an aggregate data value.
  pub fn create_insert_value(&self, agg: &Value, elem: &Value, index: usize) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildInsertValue(self.0,
    		                         agg.0,
    		                         elem.0,
    		                         index as c_uint,
    		                         NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction that extracts a value from an aggregate type.
	pub fn create_extract_value(&self, agg: &Value, index: usize) -> Value {
    Value(unsafe {
    	core::LLVMBuildExtractValue(self.0,
    		                          agg.0,
    		                          index as c_uint,
    		                          NULL_NAME.as_ptr())
   	})
  }

  unary_instr!{create_load, LLVMBuildLoad}
  unary_instr!{create_neg, LLVMBuildNeg}
  unary_instr!{create_not, LLVMBuildNot}

  bin_instr!{create_add, LLVMBuildAdd, LLVMBuildFAdd}
  bin_instr!{create_sub, LLVMBuildSub, LLVMBuildFSub}
  bin_instr!{create_mul, LLVMBuildMul, LLVMBuildFMul}
  bin_instr!{create_div, LLVMBuildSDiv, LLVMBuildFDiv}
  bin_instr!{create_rem, LLVMBuildSRem, LLVMBuildFRem}
  bin_instr!{create_shl, LLVMBuildShl}
  bin_instr!{create_ashr, LLVMBuildAShr}
  bin_instr!{create_and, LLVMBuildAnd}
  bin_instr!{create_or, LLVMBuildOr}
  bin_instr!{create_xor, LLVMBuildXor}

  /// Build an instruction to compare two values with the predicate given.
  pub fn create_cmp(&self, l: &Value, r: &Value, pred: Predicate) -> Value
  {
    self.create_cmp_internal(l, r, pred, true)
  }

  /// Build an instruction to compare two values with the predicate given.
  pub fn create_ucmp(&self, l: &Value, r: &Value, pred: Predicate) -> Value
  {
    self.create_cmp_internal(l, r, pred, false)
  }

  fn create_cmp_internal(&self, l: &Value, r: &Value,
  											 pred: Predicate, signed: bool) -> Value {
  	let (lhs_ty, rhs_ty) = (l.ty(), r.ty());
    assert_eq!(lhs_ty, rhs_ty);

    if lhs_ty.is_integer() {
	    let p = match (pred, signed) {
	    	(Predicate::Eq,    _)   => LLVMIntPredicate::LLVMIntEQ,
	    	(Predicate::NotEq, _)   => LLVMIntPredicate::LLVMIntNE,
	    	(Predicate::Lth, true)  => LLVMIntPredicate::LLVMIntSLT,
	    	(Predicate::Lth, false) => LLVMIntPredicate::LLVMIntULT,
	    	(Predicate::Leq, true)  => LLVMIntPredicate::LLVMIntSLE,
	    	(Predicate::Leq, false) => LLVMIntPredicate::LLVMIntULE,
	    	(Predicate::Gth, true)  => LLVMIntPredicate::LLVMIntSGT,
	    	(Predicate::Gth, false) => LLVMIntPredicate::LLVMIntUGT,
	    	(Predicate::Geq, true)  => LLVMIntPredicate::LLVMIntSGE,
	    	(Predicate::Geq, false) => LLVMIntPredicate::LLVMIntUGE,
	    };

	    Value(unsafe {
		    core::LLVMBuildICmp(self.0,
	    		                  p,
	     		                  l.0, r.0,
	     		                  NULL_NAME.as_ptr())
	    })

    } else if lhs_ty.is_float() {
    	let p = match pred {
        Predicate::Eq    => LLVMRealPredicate::LLVMRealOEQ,
        Predicate::NotEq => LLVMRealPredicate::LLVMRealONE,
        Predicate::Gth   => LLVMRealPredicate::LLVMRealOGT,
        Predicate::Geq   => LLVMRealPredicate::LLVMRealOGE,
        Predicate::Lth   => LLVMRealPredicate::LLVMRealOLT,
        Predicate::Leq   => LLVMRealPredicate::LLVMRealOLE
      };

   	  Value(unsafe {
      	core::LLVMBuildFCmp(self.0,
      		                 p, l.0, r.0,
      		                 NULL_NAME.as_ptr())
      })

    } else {
      panic!("expected numbers, got {:?}", lhs_ty)
    }
  }

  /// Build an instruction that computes the address of a subelement of an aggregate data
  /// structure.
  ///
  /// Basically type-safe pointer arithmetic.
  pub fn create_gep(&self, pointer: &Value, indices: &[&Value]) -> Value
  {
    let ref_array = to_llvmref_array!(indices, LLVMValueRef);

    Value(unsafe {
    	core::LLVMBuildInBoundsGEP(self.0,
    	                           pointer.0,
    	                           ref_array.as_ptr() as *mut LLVMValueRef,
    	                           indices.len() as c_uint,
    	                           NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction to select a value depending on the predecessor of the current block.
  pub fn create_phi(&self, ty: &Ty, name: &str) -> PhiNode
  {
	  PhiNode(unsafe {
	  	core::LLVMBuildPhi(self.0, ty.0, ::util::chars::from_str(name))
  	})
  }
}

#[cfg(test)]
mod tests {
	use super::*;
  use super::super::*;
  use types::LLVMTy;
  use value::{Predicate, ToValue};

	#[test]
	pub fn test_cond_br()
	{
		let jit = JitCompiler::new("test1").ok().unwrap();
    let ctx = jit.context();
    let module = jit.module();

    let func_ty = jit.create_func_ty(&u64::llvm_ty(ctx), &[&u64::llvm_ty(ctx)]);
    let func = jit.add_func("fib", &func_ty);
    let value = func.arg(0);

    let entry = func.append("entry");
    let then_bb = func.append("then_block");
    let else_bb = func.append("else_block");
    let merge_bb = func.append("merge_block");

    let builder = jit.builder();

    builder.position_at_end(&entry);
    let local = builder.create_alloca(&u64::llvm_ty(ctx));
    let cond = builder.create_cmp(&value.into(), &5u64.to_value(ctx), Predicate::Lth);
    builder.create_cond_br(&cond, &then_bb, &else_bb);

    builder.position_at_end(&then_bb);
    builder.create_store(&8u64.to_value(ctx), &local);
    builder.create_br(&merge_bb);

    builder.position_at_end(&else_bb);
    builder.create_store(&16u64.to_value(ctx), &local);
    builder.create_br(&merge_bb);

    builder.position_at_end(&merge_bb);
    let ret_val = builder.create_load(&local);
    builder.create_ret(&ret_val);

    jit.verify().unwrap();

    /*
    let ee = JitEngine::new(&module, JitOptions {opt_level: 0}).unwrap();
    ee.with_function(func, |fib: extern fn(u64) -> u64| {
      for i in 0..10 {
        if i < 5 {
          assert_eq!(8, fib(i));
        } else {
          assert_eq!(16, fib(i));
        }
      }
    });*/
	}
}<|endoftext|>


<commit_before>// TODO: Make this non public
pub mod file_naming;

use std::collections::HashMap;
use self::file_naming::{FileName, FileType, FileNameParser};

pub struct BackupSet {
    pub file_type : FileType,
    pub time : String,
    pub start_time : String,
    pub end_time : String,
    pub compressed : bool,
    pub encrypted : bool,
    pub partial : bool,
    pub manifest_path : String,
    volumes_paths : HashMap<i32, String>,
    info_set : bool,    // true if informations are set
}

impl BackupSet {
    pub fn new() -> Self {
        BackupSet{
            file_type : FileType::Full,
            time : String::new(),
            start_time : String::new(),
            end_time : String::new(),
            compressed : false,
            encrypted : false,
            partial : false,
            manifest_path : String::new(),
            volumes_paths : HashMap::new(),
            info_set : false
        }
    }

    /// Add a filename to given set. Return true if it fits.
    ///
    /// The filename will match the given set if it has the right
    /// times and is of the right type. The information will be set
    /// from the first filename given.
    pub fn add_filename(&mut self, fname : &str, pr : &FileName) -> bool {
        if !self.info_set {
            self.set_info(pr);
        }
        else {
            // check if the file is from the same backup set
            if self.file_type != pr.file_type ||
                self.time != pr.time ||
                self.start_time != pr.start_time ||
                self.end_time != pr.end_time {
                    return false;
            }
            else {
                // fix encrypted flag
                if self.encrypted != pr.encrypted &&
                    self.partial && pr.encrypted {
                        self.encrypted = pr.encrypted;
                    }
            }
        }
        // set manifest or volume number
        if pr.manifest {
            self.manifest_path = fname.to_owned();
        }
        else {
            self.volumes_paths.insert(pr.volume_number, fname.to_owned());
        }
        true
    }

    pub fn is_complete(&self) -> bool {
        !self.manifest_path.is_empty()
    }

    pub fn get_time(&self) -> &str {
        if self.time.is_empty() {
            self.end_time.as_ref()
        }
        else {
            self.time.as_ref()
        }
    }

    fn set_info(&mut self, fname : &FileName) {
        self.file_type = fname.file_type;
        self.time = fname.time.clone();
        self.start_time = fname.start_time.clone();
        self.end_time = fname.end_time.clone();
        self.compressed = fname.compressed;
        self.encrypted = fname.encrypted;
        self.partial = fname.partial;
        self.info_set = true;
    }
}

pub struct BackupChain {
    fullset : BackupSet,
    incset_list : Vec<BackupSet>,
    start_time : String,
    end_time : String
}

impl BackupChain {
    /// Create a new BackupChain starting from a full backup set.
    pub fn new(fullset : BackupSet) -> Self {
        assert_eq!(fullset.file_type, FileType::Full);
        let time = fullset.time.clone();

        BackupChain{
            fullset : fullset,
            incset_list : Vec::new(),
            start_time : time.clone(),
            end_time : time
        }
    }

    /// Adds the given incremental backkup element to the backup chain if possible,
    /// returns it back otherwise.
    pub fn add_inc(&mut self, incset : BackupSet) -> Option<BackupSet> {
        if self.end_time == incset.start_time {
            self.end_time = incset.time.clone();
            self.incset_list.push(incset);
            None
        }
        else {
            // replace the last element if the end time comes before
            let replace_last = self.incset_list.last().map_or(false,
                |last| incset.start_time == last.start_time && incset.end_time > last.end_time);
            if replace_last {
                self.end_time = incset.time.clone();
                self.incset_list.pop();
                self.incset_list.push(incset);
                None
            }
            else {
                // ignore the given incremental backup set
                Some(incset)
            }
        }
    }
}

pub type FileNameList = Vec<String>;
pub type BackupChains = Vec<BackupChain>;
type BackupSetList = Vec<BackupSet>;

pub struct CollectionsStatus {
    pub backup_chains : BackupChains,
}

impl CollectionsStatus {
    pub fn new() -> Self {
        CollectionsStatus {
            backup_chains : Vec::new()
        }
    }

    pub fn from_filename_list(filename_list : &FileNameList) -> Self {
        let mut result = Self::new();
        result.compute_backup_chains(filename_list);
        result
    }

    fn compute_backup_chains(&mut self, filename_list : &FileNameList) {
        let mut sets = self.compute_backup_sets(filename_list);
        self.sort_backup_sets(&mut sets);
        self.add_to_chains(sets);
        self.sort_chains();
    }

    fn compute_backup_sets(&self, filename_list : &FileNameList) -> BackupSetList {
        let mut sets = BackupSetList::new();
        let parser = FileNameParser::new();
        for filename in filename_list.iter() {
            if let Some(filename_info) = parser.parse(filename.as_ref()) {
                let mut inserted = false;
                for set in sets.iter_mut() {
                    if set.add_filename(filename.as_ref(), &filename_info) {
                        inserted = true;
                        break;
                    }
                }
                if !inserted {
                    let mut new_set = BackupSet::new();
                    new_set.add_filename(filename.as_ref(), &filename_info);
                    sets.push(new_set);
                }
            }
        }
        sets
    }

    fn sort_backup_sets(&self, set_list : &mut BackupSetList) {
        set_list.sort_by(|a, b| a.get_time().cmp(b.get_time()));
    }

    fn add_to_chains(&mut self, set_list : BackupSetList) {
        for set in set_list.into_iter() {
            match set.file_type {
                FileType::Full => {
                    let new_chain = BackupChain::new(set);
                    self.backup_chains.push(new_chain);
                }
                FileType::Inc => {
                    let mut rejected_set = Some(set);
                    for chain in self.backup_chains.iter_mut() {
                        rejected_set = chain.add_inc(rejected_set.unwrap());
                        if rejected_set.is_none() {
                            break;
                        }
                    }
                    if let Some(_) = rejected_set {
                        // TODO: add to orphaned sets
                    }
                }
                _ => { continue; }
            }
        }
    }

    fn sort_chains(&mut self) {
        self.backup_chains.sort_by(|a, b| a.end_time.cmp(&b.end_time));
    }
}

#[cfg(test)]
mod test {
    use super::BackupSet;
    use super::file_naming::{FileType, FileNameParser};

    #[test]
    fn parse_and_add() {
        let full1_name = "duplicity-full.20150617T182545Z.vol1.difftar.gz";
        let manifest1_name = "duplicity-full.20150617T182545Z.manifest";
        let inc1_name = "duplicity-inc.20150617T182629Z.to.20150617T182650Z.vol1.difftar.gz";

        let parser = FileNameParser::new();
        let full1 = parser.parse(full1_name).unwrap();
        let manifest1 = parser.parse(manifest1_name).unwrap();
        let inc1 = parser.parse(inc1_name).unwrap();

        let mut set = BackupSet::new();
        // add to set
        assert!(set.add_filename(full1_name, &full1));
        assert!(set.add_filename(manifest1_name, &manifest1));
        assert!(!set.add_filename(inc1_name, &inc1));
        // test results
        assert_eq!(set.file_type, FileType::Full);
        assert_eq!(set.time, "20150617t182545z");
        assert_eq!(set.start_time, "");
        assert_eq!(set.end_time, "");
        assert!(set.compressed);
        assert!(!set.encrypted);
        assert!(!set.partial);
        assert_eq!(set.manifest_path, manifest1_name);
    }
}
<commit_msg>Implemented display for collections types<commit_after>// TODO: Make this non public
pub mod file_naming;

use std::collections::HashMap;
use std::fmt::{Display, Error, Formatter};
use self::file_naming::{FileName, FileType, FileNameParser};

pub struct BackupSet {
    pub file_type : FileType,
    pub time : String,
    pub start_time : String,
    pub end_time : String,
    pub compressed : bool,
    pub encrypted : bool,
    pub partial : bool,
    pub manifest_path : String,
    volumes_paths : HashMap<i32, String>,
    info_set : bool,    // true if informations are set
}

impl BackupSet {
    pub fn new() -> Self {
        BackupSet{
            file_type : FileType::Full,
            time : String::new(),
            start_time : String::new(),
            end_time : String::new(),
            compressed : false,
            encrypted : false,
            partial : false,
            manifest_path : String::new(),
            volumes_paths : HashMap::new(),
            info_set : false
        }
    }

    /// Add a filename to given set. Return true if it fits.
    ///
    /// The filename will match the given set if it has the right
    /// times and is of the right type. The information will be set
    /// from the first filename given.
    pub fn add_filename(&mut self, fname : &str, pr : &FileName) -> bool {
        if !self.info_set {
            self.set_info(pr);
        }
        else {
            // check if the file is from the same backup set
            if self.file_type != pr.file_type ||
                self.time != pr.time ||
                self.start_time != pr.start_time ||
                self.end_time != pr.end_time {
                    return false;
            }
            else {
                // fix encrypted flag
                if self.encrypted != pr.encrypted &&
                    self.partial && pr.encrypted {
                        self.encrypted = pr.encrypted;
                    }
            }
        }
        // set manifest or volume number
        if pr.manifest {
            self.manifest_path = fname.to_owned();
        }
        else {
            self.volumes_paths.insert(pr.volume_number, fname.to_owned());
        }
        true
    }

    pub fn is_complete(&self) -> bool {
        !self.manifest_path.is_empty()
    }

    pub fn get_time(&self) -> &str {
        if self.time.is_empty() {
            self.end_time.as_ref()
        }
        else {
            self.time.as_ref()
        }
    }

    fn set_info(&mut self, fname : &FileName) {
        self.file_type = fname.file_type;
        self.time = fname.time.clone();
        self.start_time = fname.start_time.clone();
        self.end_time = fname.end_time.clone();
        self.compressed = fname.compressed;
        self.encrypted = fname.encrypted;
        self.partial = fname.partial;
        self.info_set = true;
    }
}

impl Display for BackupSet {
    fn fmt(&self, f : &mut Formatter) -> Result<(), Error> {
        match self.file_type {
            FileType::Full => {
                try!(write!(f, "Full, time: {}", self.time));
            },
            FileType::Inc => {
                try!(write!(f, "Incremental, start time: {}, end time: {}", self.start_time, self.end_time));
            },
            _ => { }
        }
        if self.compressed {
            try!(write!(f, ", compressed"));
        }
        if self.encrypted {
            try!(write!(f, ", encrypted"));
        }
        if self.partial {
            try!(write!(f, ", partial"));
        }
        if !self.manifest_path.is_empty() {
            try!(write!(f, "\n manifest: {}", self.manifest_path));
        }
        if !self.volumes_paths.is_empty() {
            try!(write!(f, "\n volumes:\n"));
            for (_, vol) in self.volumes_paths.iter() {
                try!(write!(f, " {}", vol));
            }
        }
        Ok(())
    }
}

pub struct BackupChain {
    pub fullset : BackupSet,
    pub incset_list : Vec<BackupSet>,
    pub start_time : String,
    pub end_time : String
}

impl BackupChain {
    /// Create a new BackupChain starting from a full backup set.
    pub fn new(fullset : BackupSet) -> Self {
        assert_eq!(fullset.file_type, FileType::Full);
        let time = fullset.time.clone();

        BackupChain{
            fullset : fullset,
            incset_list : Vec::new(),
            start_time : time.clone(),
            end_time : time
        }
    }

    /// Adds the given incremental backkup element to the backup chain if possible,
    /// returns it back otherwise.
    pub fn add_inc(&mut self, incset : BackupSet) -> Option<BackupSet> {
        if self.end_time == incset.start_time {
            self.end_time = incset.end_time.clone();
            self.incset_list.push(incset);
            None
        }
        else {
            // replace the last element if the end time comes before
            let replace_last = self.incset_list.last().map_or(false,
                |last| incset.start_time == last.start_time && incset.end_time > last.end_time);
            if replace_last {
                self.end_time = incset.end_time.clone();
                self.incset_list.pop();
                self.incset_list.push(incset);
                None
            }
            else {
                // ignore the given incremental backup set
                Some(incset)
            }
        }
    }
}

impl Display for BackupChain {
    fn fmt(&self, f : &mut Formatter) -> Result<(), Error> {
        try!(write!(f, "start time: {}, end time: {}\n{}",
                    &self.start_time, &self.end_time, &self.fullset));
        for inc in self.incset_list.iter() {
            try!(write!(f, "\n{}", inc));
        }
        Ok(())
    }
}

pub type FileNameList = Vec<String>;
pub type BackupChains = Vec<BackupChain>;
type BackupSetList = Vec<BackupSet>;

pub struct CollectionsStatus {
    pub backup_chains : BackupChains,
}

impl CollectionsStatus {
    pub fn new() -> Self {
        CollectionsStatus {
            backup_chains : Vec::new()
        }
    }

    pub fn from_filename_list(filename_list : &FileNameList) -> Self {
        let mut result = Self::new();
        result.compute_backup_chains(filename_list);
        result
    }

    fn compute_backup_chains(&mut self, filename_list : &FileNameList) {
        let mut sets = self.compute_backup_sets(filename_list);
        self.sort_backup_sets(&mut sets);
        self.add_to_chains(sets);
        self.sort_chains();
    }

    fn compute_backup_sets(&self, filename_list : &FileNameList) -> BackupSetList {
        let mut sets = BackupSetList::new();
        let parser = FileNameParser::new();
        for filename in filename_list.iter() {
            if let Some(filename_info) = parser.parse(filename.as_ref()) {
                let mut inserted = false;
                for set in sets.iter_mut() {
                    if set.add_filename(filename.as_ref(), &filename_info) {
                        inserted = true;
                        break;
                    }
                }
                if !inserted {
                    let mut new_set = BackupSet::new();
                    new_set.add_filename(filename.as_ref(), &filename_info);
                    sets.push(new_set);
                }
            }
        }
        sets
    }

    fn sort_backup_sets(&self, set_list : &mut BackupSetList) {
        set_list.sort_by(|a, b| a.get_time().cmp(b.get_time()));
    }

    fn add_to_chains(&mut self, set_list : BackupSetList) {
        for set in set_list.into_iter() {
            match set.file_type {
                FileType::Full => {
                    let new_chain = BackupChain::new(set);
                    self.backup_chains.push(new_chain);
                }
                FileType::Inc => {
                    let mut rejected_set = Some(set);
                    for chain in self.backup_chains.iter_mut() {
                        rejected_set = chain.add_inc(rejected_set.unwrap());
                        if rejected_set.is_none() {
                            break;
                        }
                    }
                    if let Some(_) = rejected_set {
                        // TODO: add to orphaned sets
                    }
                }
                _ => { continue; }
            }
        }
    }

    fn sort_chains(&mut self) {
        self.backup_chains.sort_by(|a, b| a.end_time.cmp(&b.end_time));
    }
}

impl Display for CollectionsStatus {
    fn fmt(&self, f : &mut Formatter) -> Result<(), Error> {
        for backup_chain in &self.backup_chains {
            try!(backup_chain.fmt(f));
        }
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::{BackupSet, CollectionsStatus};
    use super::file_naming::{FileType, FileNameParser};

    #[test]
    fn parse_and_add() {
        let full1_name = "duplicity-full.20150617T182545Z.vol1.difftar.gz";
        let manifest1_name = "duplicity-full.20150617T182545Z.manifest";
        let inc1_name = "duplicity-inc.20150617T182629Z.to.20150617T182650Z.vol1.difftar.gz";

        let parser = FileNameParser::new();
        let full1 = parser.parse(full1_name).unwrap();
        let manifest1 = parser.parse(manifest1_name).unwrap();
        let inc1 = parser.parse(inc1_name).unwrap();

        let mut set = BackupSet::new();
        // add to set
        assert!(set.add_filename(full1_name, &full1));
        assert!(set.add_filename(manifest1_name, &manifest1));
        assert!(!set.add_filename(inc1_name, &inc1));
        // test results
        assert_eq!(set.file_type, FileType::Full);
        assert_eq!(set.time, "20150617t182545z");
        assert_eq!(set.start_time, "");
        assert_eq!(set.end_time, "");
        assert!(set.compressed);
        assert!(!set.encrypted);
        assert!(!set.partial);
        assert_eq!(set.manifest_path, manifest1_name);
    }

    #[test]
    fn collection_status() {
        let filename_list = vec![
            "duplicity-full.20150617T182545Z.manifest".to_owned(),
            "duplicity-full.20150617T182545Z.vol1.difftar.gz".to_owned(),
            "duplicity-full-signatures.20150617T182545Z.sigtar.gz".to_owned(),
            "duplicity-inc.20150617T182545Z.to.20150617T182629Z.manifest".to_owned(),
            "duplicity-inc.20150617T182545Z.to.20150617T182629Z.vol1.difftar.gz".to_owned(),
            "duplicity-inc.20150617T182629Z.to.20150617T182650Z.manifest".to_owned(),
            "duplicity-inc.20150617T182629Z.to.20150617T182650Z.vol1.difftar.gz".to_owned(),
            "duplicity-new-signatures.20150617T182545Z.to.20150617T182629Z.sigtar.gz".to_owned(),
            "duplicity-new-signatures.20150617T182629Z.to.20150617T182650Z.sigtar.gz".to_owned()
        ];
        let collection_status = CollectionsStatus::from_filename_list(&filename_list);
        println!("collection: {}", collection_status);
    }
}
<|endoftext|>


<commit_before>extern crate sputnikvm;
extern crate serde_json;

mod blockchain;

pub use self::blockchain::{JSONBlock, create_block, create_context};

use serde_json::Value;
use std::str::FromStr;
use sputnikvm::{Gas, M256, U256, Address, read_hex};
use sputnikvm::vm::errors::RequireError;
use sputnikvm::vm::{VM, SeqVM, AccountCommitment, Context, Account, HashMapStorage, Patch, VMStatus};

pub fn fire_with_block(machine: &mut SeqVM, block: &JSONBlock) {
    loop {
        match machine.fire() {
            Err(RequireError::Account(address)) => {
                let account = block.request_account(address);
                machine.commit_account(account);
            },
            Err(RequireError::AccountCode(address)) => {
                let account = block.request_account_code(address);
                machine.commit_account(account);
            },
            Err(RequireError::Blockhash(number)) => {
                // The test JSON file doesn't expose any block
                // information. So those numbers are crafted by hand.
                let hash1 = M256::from_str("0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6").unwrap();
                let hash2 = M256::from_str("0xad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5").unwrap();
                let hash256 = M256::from_str("0x6ca54da2c4784ea43fd88b3402de07ae4bced597cbb19f323b7595857a6720ae").unwrap();

                let hash = if number == M256::from(1u64) {
                    hash1
                } else if number == M256::from(2u64) {
                    hash2
                } else if number == M256::from(256u64) {
                    hash256
                } else {
                    panic!();
                };

                machine.commit_blockhash(number, hash);
            },
            Ok(()) => return,
        }
    }
}

pub fn apply_to_block(machine: &SeqVM, block: &mut JSONBlock) {
    for account in machine.accounts() {
        let account = (*account).clone();
        block.apply_account(account);
    }
    for log in machine.logs() {
        let log = (*log).clone();
        block.apply_log(log);
    }
}

pub fn create_machine(v: &Value, block: &JSONBlock) -> SeqVM {
    let transaction = create_context(v);

    SeqVM::new(transaction, block.block_header(), Patch::None)
}

pub fn test_machine(v: &Value, machine: &SeqVM, block: &JSONBlock, debug: bool) -> bool {
    let ref callcreates = v["callcreates"];

    if callcreates.as_array().is_some() {
        let mut i = 0;
        for callcreate in callcreates.as_array().unwrap() {
            let data = read_hex(callcreate["data"].as_str().unwrap()).unwrap();
            let destination = {
                let destination = callcreate["destination"].as_str().unwrap();
                if destination == "" {
                    None
                } else {
                    Some(Address::from_str(destination).unwrap())
                }
            };
            let gas_limit = Gas::from_str(callcreate["gasLimit"].as_str().unwrap()).unwrap();
            let value = U256::from_str(callcreate["value"].as_str().unwrap()).unwrap();

            if i >= machine.history().len() {
                if debug {
                    print!("\n");
                    println!("Transaction check failed, expected more than {} items.", i);
                }
                return false;
            }
            let ref transaction = machine.history()[i];
            if destination.is_some() {
                if transaction.address != destination.unwrap() {
                    if debug {
                        print!("\n");
                        println!("Transaction address mismatch. 0x{:x} != 0x{:x}.", transaction.address, destination.unwrap());
                    }
                    return false;
                }
            }
            if transaction.gas_limit != gas_limit || transaction.value != value || transaction.data != data {
                if debug {
                    print!("\n");
                    println!("Transaction mismatch. gas limit 0x{:x} =?= 0x{:x}, value 0x{:x} =?= 0x{:x}, data {:?} =?= {:?}", transaction.gas_limit, gas_limit, transaction.value, value, transaction.data, data);
                }
                return false;
            }

            i = i + 1;
        }
    }

    let out = v["out"].as_str();
    let gas = v["gas"].as_str();

    if out.is_some() {
        let out = read_hex(out.unwrap()).unwrap();
        let out_ref: &[u8] = out.as_ref();
        if machine.out() != out_ref {
            if debug {
                print!("\n");
                println!("Return value check failed. {:?} != {:?}", machine.out(), out_ref);
            }

            return false;
        }
    }

    if gas.is_some() {
        let gas = Gas::from_str(gas.unwrap()).unwrap();
        if machine.available_gas() != gas {
            if debug {
                print!("\n");
                println!("Gas check failed, VM returned: 0x{:x}, expected: 0x{:x}",
                         machine.available_gas(), gas);
            }

            return false;
        }
    }

    let ref post_addresses = v["post"];

    for (address, data) in post_addresses.as_object().unwrap() {
        let address = Address::from_str(address.as_str()).unwrap();
        let balance = U256::from_str(data["balance"].as_str().unwrap()).unwrap();
        let code = read_hex(data["code"].as_str().unwrap()).unwrap();
        let code_ref: &[u8] = code.as_ref();

        if code_ref != block.account_code(address) {
            if debug {
                print!("\n");
                println!("Account code check failed for address 0x{:x}.", address);
            }

            return false;
        }
        if balance != block.balance(address) {
            if debug {
                print!("\n");
                println!("Balance check failed for address 0x{:x}.", address);
            }

            return false;
        }

        let storage = data["storage"].as_object().unwrap();
        for (index, value) in storage {
            let index = M256::from_str(index.as_str()).unwrap();
            let value = M256::from_str(value.as_str().unwrap()).unwrap();
            if value != block.account_storage(address, index) {
                if debug {
                    print!("\n");
                    println!("Storage check failed for address 0x{:x} in storage index 0x{:x}",
                             address, index);
                    println!("Expected: 0x{:x}", value);
                    println!("Actual:   0x{:x}", block.account_storage(address, index));
                }
                return false;
            }
        }
    }

    let ref expect = v["expect"];

    if expect.as_object().is_some() {
        for (address, data) in expect.as_object().unwrap() {
            let address = Address::from_str(address.as_str()).unwrap();

            let storage = data["storage"].as_object().unwrap();
            for (index, value) in storage {
                let index = M256::from_str(index.as_str()).unwrap();
                let value = M256::from_str(value.as_str().unwrap()).unwrap();
                if value != block.account_storage(address, index) {
                    if debug {
                        print!("\n");
                        println!("Storage check (expect) failed for address 0x{:x} in storage index 0x{:x}",
                                 address, index);
                        println!("Expected: 0x{:x}", value);
                        println!("Actual:   0x{:x}", block.account_storage(address, index));
                    }
                    return false;
                }
            }
        }
    }

    let ref logs = v["logs"].as_array();

    if logs.is_some() {
        let logs = logs.unwrap();

        for log in logs {
            let log = log.as_object().unwrap();

            let address = Address::from_str(log["address"].as_str().unwrap()).unwrap();
            let data = read_hex(log["data"].as_str().unwrap()).unwrap();
            let mut topics: Vec<M256> = Vec::new();

            for topic in log["topics"].as_array().unwrap() {
                topics.push(M256::from_str(topic.as_str().unwrap()).unwrap());
            }

            if !block.find_log(address, data.as_slice(), topics.as_slice()) {
                if debug {
                    print!("\n");
                    println!("Log match failed.");
                }
                return false;
            }
        }
    }

    return true;
}

fn is_ok(status: VMStatus) -> bool {
    match status {
        VMStatus::ExitedOk => true,
        _ => false,
    }
}

pub fn test_transaction(name: &str, v: &Value, debug: bool) -> bool {
    let mut block = create_block(v);
    let mut machine = create_machine(v, &block);
    fire_with_block(&mut machine, &block);
    apply_to_block(&machine, &mut block);

    println!("status: {:?}", machine.status());
    let out = v["out"].as_str();

    if out.is_some() {
        if is_ok(machine.status()) {
            if test_machine(v, &machine, &block, debug) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    } else {
        if !is_ok(machine.status()) {
            return true;
        } else {
            return false;
        }
    }
}
<commit_msg>Problem: data means code in callcreates when destination is none Solution: handle using a conditional case<commit_after>extern crate sputnikvm;
extern crate serde_json;

mod blockchain;

pub use self::blockchain::{JSONBlock, create_block, create_context};

use serde_json::Value;
use std::str::FromStr;
use sputnikvm::{Gas, M256, U256, Address, read_hex};
use sputnikvm::vm::errors::RequireError;
use sputnikvm::vm::{VM, SeqVM, AccountCommitment, Context, Account, HashMapStorage, Patch, VMStatus};

pub fn fire_with_block(machine: &mut SeqVM, block: &JSONBlock) {
    loop {
        match machine.fire() {
            Err(RequireError::Account(address)) => {
                let account = block.request_account(address);
                machine.commit_account(account);
            },
            Err(RequireError::AccountCode(address)) => {
                let account = block.request_account_code(address);
                machine.commit_account(account);
            },
            Err(RequireError::Blockhash(number)) => {
                // The test JSON file doesn't expose any block
                // information. So those numbers are crafted by hand.
                let hash1 = M256::from_str("0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6").unwrap();
                let hash2 = M256::from_str("0xad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5").unwrap();
                let hash256 = M256::from_str("0x6ca54da2c4784ea43fd88b3402de07ae4bced597cbb19f323b7595857a6720ae").unwrap();

                let hash = if number == M256::from(1u64) {
                    hash1
                } else if number == M256::from(2u64) {
                    hash2
                } else if number == M256::from(256u64) {
                    hash256
                } else {
                    panic!();
                };

                machine.commit_blockhash(number, hash);
            },
            Ok(()) => return,
        }
    }
}

pub fn apply_to_block(machine: &SeqVM, block: &mut JSONBlock) {
    for account in machine.accounts() {
        let account = (*account).clone();
        block.apply_account(account);
    }
    for log in machine.logs() {
        let log = (*log).clone();
        block.apply_log(log);
    }
}

pub fn create_machine(v: &Value, block: &JSONBlock) -> SeqVM {
    let transaction = create_context(v);

    SeqVM::new(transaction, block.block_header(), Patch::None)
}

pub fn test_machine(v: &Value, machine: &SeqVM, block: &JSONBlock, debug: bool) -> bool {
    let ref callcreates = v["callcreates"];

    if callcreates.as_array().is_some() {
        let mut i = 0;
        for callcreate in callcreates.as_array().unwrap() {
            let data = read_hex(callcreate["data"].as_str().unwrap()).unwrap();
            let destination = {
                let destination = callcreate["destination"].as_str().unwrap();
                if destination == "" {
                    None
                } else {
                    Some(Address::from_str(destination).unwrap())
                }
            };
            let gas_limit = Gas::from_str(callcreate["gasLimit"].as_str().unwrap()).unwrap();
            let value = U256::from_str(callcreate["value"].as_str().unwrap()).unwrap();

            if i >= machine.history().len() {
                if debug {
                    print!("\n");
                    println!("Transaction check failed, expected more than {} items.", i);
                }
                return false;
            }
            let ref transaction = machine.history()[i];
            if destination.is_some() {
                if transaction.address != destination.unwrap() {
                    if debug {
                        print!("\n");
                        println!("Transaction address mismatch. 0x{:x} != 0x{:x}.", transaction.address, destination.unwrap());
                    }
                    return false;
                }
            }
            if transaction.gas_limit != gas_limit || transaction.value != value || if destination.is_some() { transaction.data != data } else { transaction.code != data } {
                if debug {
                    print!("\n");
                    println!("Transaction mismatch. gas limit 0x{:x} =?= 0x{:x}, value 0x{:x} =?= 0x{:x}, data {:?} =?= {:?}", transaction.gas_limit, gas_limit, transaction.value, value, transaction.data, data);
                }
                return false;
            }

            i = i + 1;
        }
    }

    let out = v["out"].as_str();
    let gas = v["gas"].as_str();

    if out.is_some() {
        let out = read_hex(out.unwrap()).unwrap();
        let out_ref: &[u8] = out.as_ref();
        if machine.out() != out_ref {
            if debug {
                print!("\n");
                println!("Return value check failed. {:?} != {:?}", machine.out(), out_ref);
            }

            return false;
        }
    }

    if gas.is_some() {
        let gas = Gas::from_str(gas.unwrap()).unwrap();
        if machine.available_gas() != gas {
            if debug {
                print!("\n");
                println!("Gas check failed, VM returned: 0x{:x}, expected: 0x{:x}",
                         machine.available_gas(), gas);
            }

            return false;
        }
    }

    let ref post_addresses = v["post"];

    for (address, data) in post_addresses.as_object().unwrap() {
        let address = Address::from_str(address.as_str()).unwrap();
        let balance = U256::from_str(data["balance"].as_str().unwrap()).unwrap();
        let code = read_hex(data["code"].as_str().unwrap()).unwrap();
        let code_ref: &[u8] = code.as_ref();

        if code_ref != block.account_code(address) {
            if debug {
                print!("\n");
                println!("Account code check failed for address 0x{:x}.", address);
            }

            return false;
        }
        if balance != block.balance(address) {
            if debug {
                print!("\n");
                println!("Balance check failed for address 0x{:x}.", address);
            }

            return false;
        }

        let storage = data["storage"].as_object().unwrap();
        for (index, value) in storage {
            let index = M256::from_str(index.as_str()).unwrap();
            let value = M256::from_str(value.as_str().unwrap()).unwrap();
            if value != block.account_storage(address, index) {
                if debug {
                    print!("\n");
                    println!("Storage check failed for address 0x{:x} in storage index 0x{:x}",
                             address, index);
                    println!("Expected: 0x{:x}", value);
                    println!("Actual:   0x{:x}", block.account_storage(address, index));
                }
                return false;
            }
        }
    }

    let ref expect = v["expect"];

    if expect.as_object().is_some() {
        for (address, data) in expect.as_object().unwrap() {
            let address = Address::from_str(address.as_str()).unwrap();

            let storage = data["storage"].as_object().unwrap();
            for (index, value) in storage {
                let index = M256::from_str(index.as_str()).unwrap();
                let value = M256::from_str(value.as_str().unwrap()).unwrap();
                if value != block.account_storage(address, index) {
                    if debug {
                        print!("\n");
                        println!("Storage check (expect) failed for address 0x{:x} in storage index 0x{:x}",
                                 address, index);
                        println!("Expected: 0x{:x}", value);
                        println!("Actual:   0x{:x}", block.account_storage(address, index));
                    }
                    return false;
                }
            }
        }
    }

    let ref logs = v["logs"].as_array();

    if logs.is_some() {
        let logs = logs.unwrap();

        for log in logs {
            let log = log.as_object().unwrap();

            let address = Address::from_str(log["address"].as_str().unwrap()).unwrap();
            let data = read_hex(log["data"].as_str().unwrap()).unwrap();
            let mut topics: Vec<M256> = Vec::new();

            for topic in log["topics"].as_array().unwrap() {
                topics.push(M256::from_str(topic.as_str().unwrap()).unwrap());
            }

            if !block.find_log(address, data.as_slice(), topics.as_slice()) {
                if debug {
                    print!("\n");
                    println!("Log match failed.");
                }
                return false;
            }
        }
    }

    return true;
}

fn is_ok(status: VMStatus) -> bool {
    match status {
        VMStatus::ExitedOk => true,
        _ => false,
    }
}

pub fn test_transaction(name: &str, v: &Value, debug: bool) -> bool {
    let mut block = create_block(v);
    let mut machine = create_machine(v, &block);
    fire_with_block(&mut machine, &block);
    apply_to_block(&machine, &mut block);

    println!("status: {:?}", machine.status());
    let out = v["out"].as_str();

    if out.is_some() {
        if is_ok(machine.status()) {
            if test_machine(v, &machine, &block, debug) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    } else {
        if !is_ok(machine.status()) {
            return true;
        } else {
            return false;
        }
    }
}
<|endoftext|>


<commit_before>use std::str::Chars;

/// Lexer
pub struct Lexer<'a> {
  line: int,
  column: int,
  pos: int,
  iter: Chars<'a>,
  curr_ch: Option<char>,
  done: bool
}

/// Lexer tokens.
pub enum Token {
  PLUS,
  MINUS,
  INTEGER, // Any type of integer
  IDEN, // Identifier
  LPAREN,
  RPAREN,
  COLON
}

impl<'a> Lexer<'a> {
  pub fn new(input: &'a str) -> Lexer<'a> {
    let it = input.chars();
    Lexer {
      line: 0,
      column: 0,
      pos: 0,
      iter: it,
      curr_ch: None,
      done: false
    }
  }

  pub fn bump(&mut self) {
    self.curr_ch = self.iter.next();
  }
}

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

  #[test]
  fn bump() {
    let mut lex = Lexer::new(&"Hello World");
    lex.bump();
    assert_eq!(lex.curr_ch.unwrap(), 'H');
  }

}<commit_msg>added nextch_is<commit_after>use std::str::Chars;
use std::iter::Peekable;

/// Lexer
pub struct Lexer<'a> {
  line: int,
  column: int,
  pos: int,
  iter: Peekable<char, Chars<'a>>,
  curr_ch: Option<char>,
  done: bool
}

/// Lexer tokens.
pub enum Token {
  PLUS,
  MINUS,
  INTEGER, // Any type of integer
  IDEN, // Identifier
  LPAREN,
  RPAREN,
  COLON
}

impl<'a> Lexer<'a> {
  pub fn new(input: &'a str) -> Lexer<'a> {
    let it = input.chars().peekable();
    Lexer {
      line: 0,
      column: 0,
      pos: 0,
      iter: it,
      curr_ch: None,
      done: false
    }
  }

  pub fn bump(&mut self) {
    self.curr_ch = self.iter.next();
  }

  pub fn nextch_is(&mut self, ch: char) -> bool {
    self.bump();
    self.curr_ch.unwrap() == ch
  }

}

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

  #[test]
  fn bump() {
    let mut lex = Lexer::new(&"Hello World");
    lex.bump();
    assert_eq!(lex.curr_ch.unwrap(), 'H');
  }

  #[test]
  fn nextch() {
    let mut lex = Lexer::new(&"Woot");
    assert!(lex.nextch_is('W'));
  }

}<|endoftext|>