<commit_before>
use chrono;

use lib::hasher::*;
use lib::transaction::Transaction;
use std::collections::BTreeSet;
use std::collections::HashSet;
use self::chrono::offset::Utc;

#[derive(Debug)]
pub struct Blockchain {
    chain: BTreeSet<Block>,
    //not a lot of sorted options in stdlib...
    current_transactions: BTreeSet<Transaction>,
    nodes: HashSet<String>
}

#[derive(Debug)]
#[derive(Serialize)]
#[derive(PartialEq, Eq, PartialOrd, Ord)]
pub struct Block {
    pub index: usize,
    pub timestamp: i64,
    pub proof: u64,
    pub previous_hash: String,
    pub transactions: BTreeSet<Transaction>
}

impl Blockchain {
    pub fn new() -> Blockchain {
        let mut blockchain = Blockchain {
            chain: BTreeSet::new(),
            current_transactions: BTreeSet::new(),
            nodes: HashSet::new()
        };
        blockchain.new_block(100, String::from("Genesis block."));
        blockchain
    }

    ///
    /// Add a new transaction
    ///
    /// returns: the index of the block it will be added to
    pub fn new_transaction(&mut self, transaction: Transaction) -> usize {
        self.current_transactions.insert(transaction);
        //It will be added to the index of the next block
        self.last_block().index + 1
    }

    ///
    /// Mine a new block
    ///
   pub fn mine(&mut self) -> &Block {
        // We run the proof of work algorithm to get the next proof...
        let new_block_proof = self.new_block_proof();
        //Got it. Give ourselves the new coin (block?)
        //The sender is "0" to signify that this node has mined a new coin.
        self.new_transaction(Transaction::new("0".into(), "my node address".into(), 1));
        let previous_hash = self.hash_last_block();
        //Forge the new Block by adding it to the chain
        let mined_block = self.new_block(new_block_proof, previous_hash);
        &mined_block
    }

    fn create_block(&mut self, proof: u64, previous_hash: String) -> Block {
        //Current transactions get moved to this block and are cleared to start
        //collecting the next block's transactions
        let mut txns = BTreeSet::new();
        txns.append(&mut self.current_transactions);
        Block {
            index: self.chain.len() + 1,
            timestamp: Utc::now().timestamp(),
            proof: proof,
            previous_hash: previous_hash,
            transactions: txns
        }
    }

    ///
    ///Create a new Block
    ///
    fn new_block(&mut self, proof: u64, previous_hash: String) -> &Block {
        let block = self.create_block(proof, previous_hash);
        self.chain.insert(block);
        &self.chain.iter().next_back().expect("Just added element")
    }

    fn last_block(&self) -> &Block {
        //it's a double-ended iterator, and it's sorted, so it should be fast
        self.chain.iter().next_back().expect("Chain empty. Expected genesis block")
    }

    fn hash(block: &Block) -> Result<String, String> {
       self::hash(block)
    }

    ///
    ///Simple Proof of Work Algorithm:
    ///          - Find a number p' such that hash(pp') contains leading 4 zeroes, where p is the previous p'
    ///          - p is the previous proof, and p' is the new proof
    fn proof_of_work(last_proof: u64) -> u64 {
        info!("Mining from last_proof {}...", last_proof);
        let mut proof = 0;
        while !Self::valid_proof(last_proof, proof) {
             proof += 1
        }
        debug!("Took {} iterations",proof);
        return proof
    }

    /// Validates the Proof
    /// i.e. does the hash of last_proof and this proof end in 000?
    fn valid_proof(last_proof: u64, proof: u64) -> bool {

        let guess = format!("{}{}", last_proof,proof);
        let guess_hash =  self::hash_string(guess);
        let is_valid = guess_hash.starts_with("000");
        if is_valid {
            debug!("guess_hash: {}", guess_hash);
        }
        is_valid
    }

    fn new_block_proof(&self) -> u64{
        let last_block = self.last_block();
        let last_proof = last_block.proof;
        //Mine!
        Self::proof_of_work(last_proof)
    }

    fn hash_last_block(&self) -> String {
        let last_block = self.last_block();
        //TODO: Don't panic here
        Self::hash(last_block).expect("hash block failed")
    }

}

#[cfg(test)]
mod tests {
    use std::collections::HashSet;
    use blockchain::Blockchain;

    #[test]
    fn new_transaction() {
        let mut blockchain = Blockchain::new();
        let idx = blockchain.new_transaction(String::from("a"), String::from("b"), 100);
        let last_txn = blockchain.current_transactions.iter().next_back().expect("expected a txn");
        assert_eq!(last_txn.sender, String::from("a"));
        assert_eq!(last_txn.recipient, String::from("b"));
        assert_eq!(last_txn.amount, 100);
    }

     #[test]
    fn new_block() {
        let mut blockchain = Blockchain::new();
        blockchain.new_transaction(String::from("a"), String::from("b"), 100);

        let a = blockchain.current_transactions.len();
        assert_eq!(1, a , "1 transaction");

        blockchain.new_block(2, String::from("abc"));

        let b = blockchain.current_transactions.len();
        assert_eq!(0, b, "New block should clear transactions (which were on the previous block");

    }

    #[test]
    fn hash() {
        let mut blockchain = Blockchain::new();
        blockchain.new_block(2, String::from("abc"));
        let block = blockchain.last_block();
        let hash = Blockchain::hash(block);
        let hash2 = Blockchain::hash(block);
        println!("{:?}", hash);
        assert!(hash.is_ok());
        assert_eq!(hash.unwrap(), hash2.unwrap(), "Expected same block to hash to the same value");
        //assert!(hash.unwrap().len() > 10, "expected a longer hash");
    }

    #[test]
    fn valid_proof_false() {
        let mut blockchain = Blockchain::new();
        assert_eq!(Blockchain::valid_proof(100,1), false);
    }

    #[test]
    fn proof_of_work() {
        let mut blockchain = Blockchain::new();
        let proof = blockchain.new_block_proof();
        println!("Proof of work: {}", proof);
        assert!(proof > 1, "expected a higher proof");
        assert!(Blockchain::valid_proof(100, proof));
    }

}

// import hashlib
// import json
// from time import time
// from urllib.parse import urlparse
// from uuid import uuid4

// import requests
// from flask import Flask, jsonify, request

// class Blockchain(object):
//     def __init__(self):
//         self.current_transactions = []
//         self.chain = []
//         self.nodes = set()

//         # Create the genesis block
//         self.new_block(previous_hash=1, proof=100)

//     def register_node(self, address):
//         """
//         Add a new node to the list of nodes

//         :param address: <str> Address of node. Eg. 'http://192.168.0.5:5000'
//         :return: None
//         """

//         parsed_url = urlparse(address)
//         self.nodes.add(parsed_url.netloc)

//     def valid_chain(self, chain):
//         """
//         Determine if a given blockchain is valid

//         :param chain: <list> A blockchain
//         :return: <bool> True if valid, False if not
//         """

//         last_block = chain[0]
//         current_index = 1

//         while current_index < len(chain):
//             block = chain[current_index]
//             print(f'{last_block}')
//             print(f'{block}')
//             print("\n-----------\n")
//             # Check that the hash of the block is correct
//             if block['previous_hash'] != self.hash(last_block):
//                 return False

//             # Check that the Proof of Work is correct
//             if not self.valid_proof(last_block['proof'], block['proof']):
//                 return False

//             last_block = block
//             current_index += 1

//         return True

//     def resolve_conflicts(self):
//         """
//         This is our consensus algorithm, it resolves conflicts
//         by replacing our chain with the longest one in the network.

//         :return: <bool> True if our chain was replaced, False if not
//         """

//         neighbours = self.nodes
//         new_chain = None

//         # We're only looking for chains longer than ours
//         max_length = len(self.chain)

//         # Grab and verify the chains from all the nodes in our network
//         for node in neighbours:
//             response = requests.get(f'http://{node}/chain')

//             if response.status_code == 200:
//                 length = response.json()['length']
//                 chain = response.json()['chain']

//                 # Check if the length is longer and the chain is valid
//                 if length > max_length and self.valid_chain(chain):
//                     max_length = length
//                     new_chain = chain

//         # Replace our chain if we discovered a new, valid chain longer than ours
//         if new_chain:
//             self.chain = new_chain
//             return True

//         return False

//     def new_block(self, proof, previous_hash=None):
//         """
//         Create a new Block in the Blockchain

//         :param proof: <int> The proof given by the Proof of Work algorithm
//         :param previous_hash: (Optional) <str> Hash of previous Block
//         :return: <dict> New Block
//         """

//         block = {
//             'index': len(self.chain) + 1,
//             'timestamp': time(),
//             'transactions': self.current_transactions,
//             'proof': proof,
//             'previous_hash': previous_hash or self.hash(self.chain[-1]),
//         }

//         # Reset the current list of transactions
//         self.current_transactions = []

//         self.chain.append(block)
//         return block

//     def new_transaction(self, sender, recipient, amount):
//         """
//         Creates a new transaction to go into the next mined Block

//         :param sender: <str> Address of the Sender
//         :param recipient: <str> Address of the Recipient
//         :param amount: <int> Amount
//         :return: <int> The index of the Block that will hold this transaction
//         """
//         self.current_transactions.append({
//             'sender': sender,
//             'recipient': recipient,
//             'amount': amount,
//         })

//         return self.last_block['index'] + 1

//     @property
//     def last_block(self):
//         return self.chain[-1]

//     @staticmethod
//     def hash(block):
//         """
//         Creates a SHA-256 hash of a Block

//         :param block: <dict> Block
//         :return: <str>
//         """

//         # We must make sure that the Dictionary is Ordered, or we'll have inconsistent hashes
//         block_string = json.dumps(block, sort_keys=True).encode()
//         return hashlib.sha256(block_string).hexdigest()

//     def proof_of_work(self, last_proof):
//         """
//         Simple Proof of Work Algorithm:
//          - Find a number p' such that hash(pp') contains leading 4 zeroes, where p is the previous p'
//          - p is the previous proof, and p' is the new proof

//         :param last_proof: <int>
//         :return: <int>
//         """

//         proof = 0
//         while self.valid_proof(last_proof, proof) is False:
//             proof += 1

//         return proof

//     @staticmethod
//     def valid_proof(last_proof, proof):
//         """
//         Validates the Proof

//         :param last_proof: <int> Previous Proof
//         :param proof: <int> Current Proof
//         :return: <bool> True if correct, False if not.
//         """

//         guess = f'{last_proof}{proof}'.encode()
//         guess_hash = hashlib.sha256(guess).hexdigest()
//         return guess_hash[:4] == "0000"

// # Instantiate the Node
// app = Flask(__name__)

// # Generate a globally unique address for this node
// node_identifier = str(uuid4()).replace('-', '')

// # Instantiate the Blockchain
// blockchain = Blockchain()

// @app.route('/mine', methods=['GET'])
// def mine():
//     # We run the proof of work algorithm to get the next proof...
//     last_block = blockchain.last_block
//     last_proof = last_block['proof']
//     proof = blockchain.proof_of_work(last_proof)

//     # We must receive a reward for finding the proof.
//     # The sender is "0" to signify that this node has mined a new coin.
//     blockchain.new_transaction(
//         sender="0",
//         recipient=node_identifier,
//         amount=1,
//     )

//     # Forge the new Block by adding it to the chain
//     block = blockchain.new_block(proof)

//     response = {
//         'message': "New Block Forged",
//         'index': block['index'],
//         'transactions': block['transactions'],
//         'proof': block['proof'],
//         'previous_hash': block['previous_hash'],
//     }
//     return jsonify(response), 200

// @app.route('/transactions/new', methods=['POST'])
// def new_transaction():
//     values = request.get_json()

//     # Check that the required fields are in the POST'ed data
//     required = ['sender', 'recipient', 'amount']
//     if not all(k in values for k in required):
//         return 'Missing values', 400

//     # Create a new Transaction
//     index = blockchain.new_transaction(values['sender'], values['recipient'], values['amount'])

//     response = {'message': f'Transaction will be added to Block {index}'}
//     return jsonify(response), 201

// @app.route('/chain', methods=['GET'])
// def full_chain():
//     response = {
//         'chain': blockchain.chain,
//         'length': len(blockchain.chain),
//     }
//     return jsonify(response), 200

// @app.route('/nodes/register', methods=['POST'])
// def register_nodes():
//     values = request.get_json()

//     nodes = values.get('nodes')
//     if nodes is None:
//         return "Error: Please supply a valid list of nodes", 400

//     for node in nodes:
//         blockchain.register_node(node)

//     response = {
//         'message': 'New nodes have been added',
//         'total_nodes': list(blockchain.nodes),
//     }
//     return jsonify(response), 201

// @app.route('/nodes/resolve', methods=['GET'])
// def consensus():
//     replaced = blockchain.resolve_conflicts()

//     if replaced:
//         response = {
//             'message': 'Our chain was replaced',
//             'new_chain': blockchain.chain
//         }
//     else:
//         response = {
//             'message': 'Our chain is authoritative',
//             'chain': blockchain.chain
//         }

//     return jsonify(response), 200

// if __name__ == '__main__':
//     app.run(host='0.0.0.0', port=5000)<commit_msg>fixed tests<commit_after>
use chrono;

use lib::hasher::*;
use lib::transaction::Transaction;
use std::collections::BTreeSet;
use std::collections::HashSet;
use self::chrono::offset::Utc;

#[derive(Debug)]
pub struct Blockchain {
    chain: BTreeSet<Block>,
    //not a lot of sorted options in stdlib...
    current_transactions: BTreeSet<Transaction>,
    nodes: HashSet<String>
}

#[derive(Debug)]
#[derive(Serialize)]
#[derive(PartialEq, Eq, PartialOrd, Ord)]
pub struct Block {
    pub index: usize,
    pub timestamp: i64,
    pub proof: u64,
    pub previous_hash: String,
    pub transactions: BTreeSet<Transaction>
}

impl Blockchain {
    pub fn new() -> Blockchain {
        let mut blockchain = Blockchain {
            chain: BTreeSet::new(),
            current_transactions: BTreeSet::new(),
            nodes: HashSet::new()
        };
        blockchain.new_block(100, String::from("Genesis block."));
        blockchain
    }

    ///
    /// Add a new transaction
    ///
    /// returns: the index of the block it will be added to
    pub fn new_transaction(&mut self, transaction: Transaction) -> usize {
        self.current_transactions.insert(transaction);
        //It will be added to the index of the next block
        self.last_block().index + 1
    }

    ///
    /// Mine a new block
    ///
   pub fn mine(&mut self) -> &Block {
        // We run the proof of work algorithm to get the next proof...
        let new_block_proof = self.new_block_proof();
        //Got it. Give ourselves the new coin (block?)
        //The sender is "0" to signify that this node has mined a new coin.
        self.new_transaction(Transaction::new("0".into(), "my node address".into(), 1));
        let previous_hash = self.hash_last_block();
        //Forge the new Block by adding it to the chain
        let mined_block = self.new_block(new_block_proof, previous_hash);
        &mined_block
    }

    fn create_block(&mut self, proof: u64, previous_hash: String) -> Block {
        //Current transactions get moved to this block and are cleared to start
        //collecting the next block's transactions
        let mut txns = BTreeSet::new();
        txns.append(&mut self.current_transactions);
        Block {
            index: self.chain.len() + 1,
            timestamp: Utc::now().timestamp(),
            proof: proof,
            previous_hash: previous_hash,
            transactions: txns
        }
    }

    ///
    ///Create a new Block
    ///
    fn new_block(&mut self, proof: u64, previous_hash: String) -> &Block {
        let block = self.create_block(proof, previous_hash);
        self.chain.insert(block);
        &self.chain.iter().next_back().expect("Just added element")
    }

    fn last_block(&self) -> &Block {
        //it's a double-ended iterator, and it's sorted, so it should be fast
        self.chain.iter().next_back().expect("Chain empty. Expected genesis block")
    }

    fn hash(block: &Block) -> Result<String, String> {
       self::hash(block)
    }

    ///
    ///Simple Proof of Work Algorithm:
    ///          - Find a number p' such that hash(pp') contains leading 4 zeroes, where p is the previous p'
    ///          - p is the previous proof, and p' is the new proof
    fn proof_of_work(last_proof: u64) -> u64 {
        info!("Mining from last_proof {}...", last_proof);
        let mut proof = 0;
        while !Self::valid_proof(last_proof, proof) {
             proof += 1
        }
        debug!("Took {} iterations",proof);
        return proof
    }

    /// Validates the Proof
    /// i.e. does the hash of last_proof and this proof end in 000?
    fn valid_proof(last_proof: u64, proof: u64) -> bool {

        let guess = format!("{}{}", last_proof,proof);
        let guess_hash =  self::hash_string(guess);
        let is_valid = guess_hash.starts_with("000");
        if is_valid {
            debug!("guess_hash: {}", guess_hash);
        }
        is_valid
    }

    fn new_block_proof(&self) -> u64{
        let last_block = self.last_block();
        let last_proof = last_block.proof;
        //Mine!
        Self::proof_of_work(last_proof)
    }

    fn hash_last_block(&self) -> String {
        let last_block = self.last_block();
        //TODO: Don't panic here
        Self::hash(last_block).expect("hash block failed")
    }
}

#[cfg(test)]
mod tests {
    use lib::blockchain::Blockchain;
    use lib::transaction::Transaction;

    #[test]
    fn new_transaction() {
        let mut blockchain = Blockchain::new();
        let txn = Transaction::new(String::from("a"), String::from("b"), 100);
        let _idx = blockchain.new_transaction(txn);
        let last_txn = blockchain.current_transactions.iter().next_back().expect("expected a txn");
        assert_eq!(last_txn.sender, String::from("a"));
        assert_eq!(last_txn.recipient, String::from("b"));
        assert_eq!(last_txn.amount, 100);
    }

     #[test]
    fn new_block() {
        let mut blockchain = Blockchain::new();
        let txn = Transaction::new(String::from("a"), String::from("b"), 100);
        blockchain.new_transaction(txn);

        let a = blockchain.current_transactions.len();
        assert_eq!(1, a , "1 transaction");

        blockchain.new_block(2, String::from("abc"));

        let b = blockchain.current_transactions.len();
        assert_eq!(0, b, "New block should clear transactions (which were on the previous block");

    }

    #[test]
    fn hash() {
        let mut blockchain = Blockchain::new();
        blockchain.new_block(2, String::from("abc"));
        let block = blockchain.last_block();
        let hash = Blockchain::hash(block);
        let hash2 = Blockchain::hash(block);
        println!("{:?}", hash);
        assert!(hash.is_ok());
        assert_eq!(hash.unwrap(), hash2.unwrap(), "Expected same block to hash to the same value");
        //assert!(hash.unwrap().len() > 10, "expected a longer hash");
    }

    #[test]
    fn valid_proof_false() {
        assert_eq!(Blockchain::valid_proof(100,1), false);
    }

    #[test]
    fn proof_of_work() {
        let blockchain = Blockchain::new();
        let proof = blockchain.new_block_proof();
        println!("Proof of work: {}", proof);
        assert!(proof > 1, "expected a higher proof");
        assert!(Blockchain::valid_proof(100, proof));
    }

}

// import hashlib
// import json
// from time import time
// from urllib.parse import urlparse
// from uuid import uuid4

// import requests
// from flask import Flask, jsonify, request

// class Blockchain(object):
//     def __init__(self):
//         self.current_transactions = []
//         self.chain = []
//         self.nodes = set()

//         # Create the genesis block
//         self.new_block(previous_hash=1, proof=100)

//     def register_node(self, address):
//         """
//         Add a new node to the list of nodes

//         :param address: <str> Address of node. Eg. 'http://192.168.0.5:5000'
//         :return: None
//         """

//         parsed_url = urlparse(address)
//         self.nodes.add(parsed_url.netloc)

//     def valid_chain(self, chain):
//         """
//         Determine if a given blockchain is valid

//         :param chain: <list> A blockchain
//         :return: <bool> True if valid, False if not
//         """

//         last_block = chain[0]
//         current_index = 1

//         while current_index < len(chain):
//             block = chain[current_index]
//             print(f'{last_block}')
//             print(f'{block}')
//             print("\n-----------\n")
//             # Check that the hash of the block is correct
//             if block['previous_hash'] != self.hash(last_block):
//                 return False

//             # Check that the Proof of Work is correct
//             if not self.valid_proof(last_block['proof'], block['proof']):
//                 return False

//             last_block = block
//             current_index += 1

//         return True

//     def resolve_conflicts(self):
//         """
//         This is our consensus algorithm, it resolves conflicts
//         by replacing our chain with the longest one in the network.

//         :return: <bool> True if our chain was replaced, False if not
//         """

//         neighbours = self.nodes
//         new_chain = None

//         # We're only looking for chains longer than ours
//         max_length = len(self.chain)

//         # Grab and verify the chains from all the nodes in our network
//         for node in neighbours:
//             response = requests.get(f'http://{node}/chain')

//             if response.status_code == 200:
//                 length = response.json()['length']
//                 chain = response.json()['chain']

//                 # Check if the length is longer and the chain is valid
//                 if length > max_length and self.valid_chain(chain):
//                     max_length = length
//                     new_chain = chain

//         # Replace our chain if we discovered a new, valid chain longer than ours
//         if new_chain:
//             self.chain = new_chain
//             return True

//         return False

//     def new_block(self, proof, previous_hash=None):
//         """
//         Create a new Block in the Blockchain

//         :param proof: <int> The proof given by the Proof of Work algorithm
//         :param previous_hash: (Optional) <str> Hash of previous Block
//         :return: <dict> New Block
//         """

//         block = {
//             'index': len(self.chain) + 1,
//             'timestamp': time(),
//             'transactions': self.current_transactions,
//             'proof': proof,
//             'previous_hash': previous_hash or self.hash(self.chain[-1]),
//         }

//         # Reset the current list of transactions
//         self.current_transactions = []

//         self.chain.append(block)
//         return block

//     def new_transaction(self, sender, recipient, amount):
//         """
//         Creates a new transaction to go into the next mined Block

//         :param sender: <str> Address of the Sender
//         :param recipient: <str> Address of the Recipient
//         :param amount: <int> Amount
//         :return: <int> The index of the Block that will hold this transaction
//         """
//         self.current_transactions.append({
//             'sender': sender,
//             'recipient': recipient,
//             'amount': amount,
//         })

//         return self.last_block['index'] + 1

//     @property
//     def last_block(self):
//         return self.chain[-1]

//     @staticmethod
//     def hash(block):
//         """
//         Creates a SHA-256 hash of a Block

//         :param block: <dict> Block
//         :return: <str>
//         """

//         # We must make sure that the Dictionary is Ordered, or we'll have inconsistent hashes
//         block_string = json.dumps(block, sort_keys=True).encode()
//         return hashlib.sha256(block_string).hexdigest()

//     def proof_of_work(self, last_proof):
//         """
//         Simple Proof of Work Algorithm:
//          - Find a number p' such that hash(pp') contains leading 4 zeroes, where p is the previous p'
//          - p is the previous proof, and p' is the new proof

//         :param last_proof: <int>
//         :return: <int>
//         """

//         proof = 0
//         while self.valid_proof(last_proof, proof) is False:
//             proof += 1

//         return proof

//     @staticmethod
//     def valid_proof(last_proof, proof):
//         """
//         Validates the Proof

//         :param last_proof: <int> Previous Proof
//         :param proof: <int> Current Proof
//         :return: <bool> True if correct, False if not.
//         """

//         guess = f'{last_proof}{proof}'.encode()
//         guess_hash = hashlib.sha256(guess).hexdigest()
//         return guess_hash[:4] == "0000"

// # Instantiate the Node
// app = Flask(__name__)

// # Generate a globally unique address for this node
// node_identifier = str(uuid4()).replace('-', '')

// # Instantiate the Blockchain
// blockchain = Blockchain()

// @app.route('/mine', methods=['GET'])
// def mine():
//     # We run the proof of work algorithm to get the next proof...
//     last_block = blockchain.last_block
//     last_proof = last_block['proof']
//     proof = blockchain.proof_of_work(last_proof)

//     # We must receive a reward for finding the proof.
//     # The sender is "0" to signify that this node has mined a new coin.
//     blockchain.new_transaction(
//         sender="0",
//         recipient=node_identifier,
//         amount=1,
//     )

//     # Forge the new Block by adding it to the chain
//     block = blockchain.new_block(proof)

//     response = {
//         'message': "New Block Forged",
//         'index': block['index'],
//         'transactions': block['transactions'],
//         'proof': block['proof'],
//         'previous_hash': block['previous_hash'],
//     }
//     return jsonify(response), 200

// @app.route('/transactions/new', methods=['POST'])
// def new_transaction():
//     values = request.get_json()

//     # Check that the required fields are in the POST'ed data
//     required = ['sender', 'recipient', 'amount']
//     if not all(k in values for k in required):
//         return 'Missing values', 400

//     # Create a new Transaction
//     index = blockchain.new_transaction(values['sender'], values['recipient'], values['amount'])

//     response = {'message': f'Transaction will be added to Block {index}'}
//     return jsonify(response), 201

// @app.route('/chain', methods=['GET'])
// def full_chain():
//     response = {
//         'chain': blockchain.chain,
//         'length': len(blockchain.chain),
//     }
//     return jsonify(response), 200

// @app.route('/nodes/register', methods=['POST'])
// def register_nodes():
//     values = request.get_json()

//     nodes = values.get('nodes')
//     if nodes is None:
//         return "Error: Please supply a valid list of nodes", 400

//     for node in nodes:
//         blockchain.register_node(node)

//     response = {
//         'message': 'New nodes have been added',
//         'total_nodes': list(blockchain.nodes),
//     }
//     return jsonify(response), 201

// @app.route('/nodes/resolve', methods=['GET'])
// def consensus():
//     replaced = blockchain.resolve_conflicts()

//     if replaced:
//         response = {
//             'message': 'Our chain was replaced',
//             'new_chain': blockchain.chain
//         }
//     else:
//         response = {
//             'message': 'Our chain is authoritative',
//             'chain': blockchain.chain
//         }

//     return jsonify(response), 200

// if __name__ == '__main__':
//     app.run(host='0.0.0.0', port=5000)<|endoftext|>


<commit_before>//! Randomization of big integers

use rand::prelude::*;
use rand::distributions::uniform::{SampleUniform, UniformSampler};

use BigInt;
use BigUint;
use Sign::*;

use big_digit::BigDigit;
use bigint::{magnitude, into_magnitude};

use traits::Zero;
use integer::Integer;

pub trait RandBigInt {
    /// Generate a random `BigUint` of the given bit size.
    fn gen_biguint(&mut self, bit_size: usize) -> BigUint;

    /// Generate a random BigInt of the given bit size.
    fn gen_bigint(&mut self, bit_size: usize) -> BigInt;

    /// Generate a random `BigUint` less than the given bound. Fails
    /// when the bound is zero.
    fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint;

    /// Generate a random `BigUint` within the given range. The lower
    /// bound is inclusive; the upper bound is exclusive. Fails when
    /// the upper bound is not greater than the lower bound.
    fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint;

    /// Generate a random `BigInt` within the given range. The lower
    /// bound is inclusive; the upper bound is exclusive. Fails when
    /// the upper bound is not greater than the lower bound.
    fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt;
}

impl<R: Rng + ?Sized> RandBigInt for R {
    fn gen_biguint(&mut self, bit_size: usize) -> BigUint {
        use super::big_digit::BITS;
        let (digits, rem) = bit_size.div_rem(&BITS);
        let mut data = Vec::with_capacity(digits + 1);
        for _ in 0..digits {
            data.push(self.gen());
        }
        if rem > 0 {
            let final_digit: BigDigit = self.gen();
            data.push(final_digit >> (BITS - rem));
        }
        BigUint::new(data)
    }

    fn gen_bigint(&mut self, bit_size: usize) -> BigInt {
        loop {
            // Generate a random BigUint...
            let biguint = self.gen_biguint(bit_size);
            // ...and then randomly assign it a Sign...
            let sign = if biguint.is_zero() {
                // ...except that if the BigUint is zero, we need to try
                // again with probability 0.5. This is because otherwise,
                // the probability of generating a zero BigInt would be
                // double that of any other number.
                if self.gen() {
                    continue;
                } else {
                    NoSign
                }
            } else if self.gen() {
                Plus
            } else {
                Minus
            };
            return BigInt::from_biguint(sign, biguint);
        }
    }

    fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint {
        assert!(!bound.is_zero());
        let bits = bound.bits();
        loop {
            let n = self.gen_biguint(bits);
            if n < *bound {
                return n;
            }
        }
    }

    fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint {
        assert!(*lbound < *ubound);
        if lbound.is_zero() {
            self.gen_biguint_below(ubound)
        } else {
            lbound + self.gen_biguint_below(&(ubound - lbound))
        }
    }

    fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt {
        assert!(*lbound < *ubound);
        if lbound.is_zero() {
            BigInt::from(self.gen_biguint_below(magnitude(&ubound)))
        } else if ubound.is_zero() {
            lbound + BigInt::from(self.gen_biguint_below(magnitude(&lbound)))
        } else {
            let delta = ubound - lbound;
            lbound + BigInt::from(self.gen_biguint_below(magnitude(&delta)))
        }
    }
}

/// The back-end implementing rand's `UniformSampler` for `BigUint`.
#[derive(Clone, Debug)]
pub struct UniformBigUint {
    base: BigUint,
    len: BigUint,
}

impl UniformSampler for UniformBigUint {
    type X = BigUint;

    #[inline]
    fn new(low: Self::X, high: Self::X) -> Self {
        assert!(low < high);
        UniformBigUint {
            len: high - &low,
            base: low,
        }
    }

    #[inline]
    fn new_inclusive(low: Self::X, high: Self::X) -> Self {
        assert!(low <= high);
        Self::new(low, high + 1u32)
    }

    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
        &self.base + rng.gen_biguint_below(&self.len)
    }

    #[inline]
    fn sample_single<R: Rng + ?Sized>(low: Self::X, high: Self::X, rng: &mut R) -> Self::X {
        rng.gen_biguint_range(&low, &high)
    }
}

impl SampleUniform for BigUint {
    type Sampler = UniformBigUint;
}

/// The back-end implementing rand's `UniformSampler` for `BigInt`.
#[derive(Clone, Debug)]
pub struct UniformBigInt {
    base: BigInt,
    len: BigUint,
}

impl UniformSampler for UniformBigInt {
    type X = BigInt;

    #[inline]
    fn new(low: Self::X, high: Self::X) -> Self {
        assert!(low < high);
        UniformBigInt {
            len: into_magnitude(high - &low),
            base: low,
        }
    }

    #[inline]
    fn new_inclusive(low: Self::X, high: Self::X) -> Self {
        assert!(low <= high);
        Self::new(low, high + 1u32)
    }

    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
        &self.base + BigInt::from(rng.gen_biguint_below(&self.len))
    }

    #[inline]
    fn sample_single<R: Rng + ?Sized>(low: Self::X, high: Self::X, rng: &mut R) -> Self::X {
        rng.gen_bigint_range(&low, &high)
    }
}

impl SampleUniform for BigInt {
    type Sampler = UniformBigInt;
}

/// A random distribution for `BigUint` and `BigInt` values of a particular bit size.
#[derive(Clone, Copy, Debug)]
pub struct RandomBits {
    bits: usize,
}

impl RandomBits {
    #[inline]
    pub fn new(bits: usize) -> RandomBits {
        RandomBits { bits }
    }
}

impl Distribution<BigUint> for RandomBits {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigUint {
        rng.gen_biguint(self.bits)
    }
}

impl Distribution<BigInt> for RandomBits {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigInt {
        rng.gen_bigint(self.bits)
    }
}
<commit_msg>switch gen_biguint to fill_bytes<commit_after>//! Randomization of big integers

use rand::prelude::*;
use rand::distributions::uniform::{SampleUniform, UniformSampler};
use rand::AsByteSliceMut;

use BigInt;
use BigUint;
use Sign::*;

use big_digit::BigDigit;
use bigint::{magnitude, into_magnitude};

use traits::Zero;
use integer::Integer;

pub trait RandBigInt {
    /// Generate a random `BigUint` of the given bit size.
    fn gen_biguint(&mut self, bit_size: usize) -> BigUint;

    /// Generate a random BigInt of the given bit size.
    fn gen_bigint(&mut self, bit_size: usize) -> BigInt;

    /// Generate a random `BigUint` less than the given bound. Fails
    /// when the bound is zero.
    fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint;

    /// Generate a random `BigUint` within the given range. The lower
    /// bound is inclusive; the upper bound is exclusive. Fails when
    /// the upper bound is not greater than the lower bound.
    fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint;

    /// Generate a random `BigInt` within the given range. The lower
    /// bound is inclusive; the upper bound is exclusive. Fails when
    /// the upper bound is not greater than the lower bound.
    fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt;
}

impl<R: Rng + ?Sized> RandBigInt for R {
    fn gen_biguint(&mut self, bit_size: usize) -> BigUint {
        use super::big_digit::BITS;
        let (digits, rem) = bit_size.div_rem(&BITS);
        let mut data = vec![BigDigit::default(); digits + (rem > 0) as usize];
        // `fill_bytes` is faster than many `gen::<u32>` calls
        self.fill_bytes(data[..].as_byte_slice_mut());
        // Swap bytes per the `Rng::fill` source. This might be
        // unnecessary if reproducibility across architectures is not
        // desired.
        data.to_le();
        if rem > 0 {
            data[digits] >>= BITS - rem;
        }
        BigUint::new(data)
    }

    fn gen_bigint(&mut self, bit_size: usize) -> BigInt {
        loop {
            // Generate a random BigUint...
            let biguint = self.gen_biguint(bit_size);
            // ...and then randomly assign it a Sign...
            let sign = if biguint.is_zero() {
                // ...except that if the BigUint is zero, we need to try
                // again with probability 0.5. This is because otherwise,
                // the probability of generating a zero BigInt would be
                // double that of any other number.
                if self.gen() {
                    continue;
                } else {
                    NoSign
                }
            } else if self.gen() {
                Plus
            } else {
                Minus
            };
            return BigInt::from_biguint(sign, biguint);
        }
    }

    fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint {
        assert!(!bound.is_zero());
        let bits = bound.bits();
        loop {
            let n = self.gen_biguint(bits);
            if n < *bound {
                return n;
            }
        }
    }

    fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint {
        assert!(*lbound < *ubound);
        if lbound.is_zero() {
            self.gen_biguint_below(ubound)
        } else {
            lbound + self.gen_biguint_below(&(ubound - lbound))
        }
    }

    fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt {
        assert!(*lbound < *ubound);
        if lbound.is_zero() {
            BigInt::from(self.gen_biguint_below(magnitude(&ubound)))
        } else if ubound.is_zero() {
            lbound + BigInt::from(self.gen_biguint_below(magnitude(&lbound)))
        } else {
            let delta = ubound - lbound;
            lbound + BigInt::from(self.gen_biguint_below(magnitude(&delta)))
        }
    }
}

/// The back-end implementing rand's `UniformSampler` for `BigUint`.
#[derive(Clone, Debug)]
pub struct UniformBigUint {
    base: BigUint,
    len: BigUint,
}

impl UniformSampler for UniformBigUint {
    type X = BigUint;

    #[inline]
    fn new(low: Self::X, high: Self::X) -> Self {
        assert!(low < high);
        UniformBigUint {
            len: high - &low,
            base: low,
        }
    }

    #[inline]
    fn new_inclusive(low: Self::X, high: Self::X) -> Self {
        assert!(low <= high);
        Self::new(low, high + 1u32)
    }

    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
        &self.base + rng.gen_biguint_below(&self.len)
    }

    #[inline]
    fn sample_single<R: Rng + ?Sized>(low: Self::X, high: Self::X, rng: &mut R) -> Self::X {
        rng.gen_biguint_range(&low, &high)
    }
}

impl SampleUniform for BigUint {
    type Sampler = UniformBigUint;
}

/// The back-end implementing rand's `UniformSampler` for `BigInt`.
#[derive(Clone, Debug)]
pub struct UniformBigInt {
    base: BigInt,
    len: BigUint,
}

impl UniformSampler for UniformBigInt {
    type X = BigInt;

    #[inline]
    fn new(low: Self::X, high: Self::X) -> Self {
        assert!(low < high);
        UniformBigInt {
            len: into_magnitude(high - &low),
            base: low,
        }
    }

    #[inline]
    fn new_inclusive(low: Self::X, high: Self::X) -> Self {
        assert!(low <= high);
        Self::new(low, high + 1u32)
    }

    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
        &self.base + BigInt::from(rng.gen_biguint_below(&self.len))
    }

    #[inline]
    fn sample_single<R: Rng + ?Sized>(low: Self::X, high: Self::X, rng: &mut R) -> Self::X {
        rng.gen_bigint_range(&low, &high)
    }
}

impl SampleUniform for BigInt {
    type Sampler = UniformBigInt;
}

/// A random distribution for `BigUint` and `BigInt` values of a particular bit size.
#[derive(Clone, Copy, Debug)]
pub struct RandomBits {
    bits: usize,
}

impl RandomBits {
    #[inline]
    pub fn new(bits: usize) -> RandomBits {
        RandomBits { bits }
    }
}

impl Distribution<BigUint> for RandomBits {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigUint {
        rng.gen_biguint(self.bits)
    }
}

impl Distribution<BigInt> for RandomBits {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigInt {
        rng.gen_bigint(self.bits)
    }
}
<|endoftext|>


<commit_before>use clap::{self, Arg, App, SubCommand};
use std::io::{self, Write};
use std::process;
use std::path::PathBuf;
use std::error;
use std::result;
use std::fmt;
use mprovision as mp;

#[derive(Debug, PartialEq)]
pub enum Command {
    List(ListParams),
    Cleanup(Option<PathBuf>),
}

#[derive(Debug, Default, PartialEq)]
pub struct ListParams {
    pub filter: Option<String>,
    pub expires_in_days: Option<i64>,
    pub directory: Option<PathBuf>,
}

pub type Result = result::Result<Command, Error>;

#[derive(Debug)]
pub enum Error {
    Lib(mp::Error),
    Clap(clap::Error),
    Custom(String),
}

impl Error {
    pub fn exit(&self) -> ! {
        match *self {
            Error::Clap(ref e) => e.exit(),
            _ => {
                writeln!(&mut io::stderr(), "{}", self).unwrap();
                process::exit(1);
            }
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Lib(ref e) => e.description(),
            Error::Clap(ref e) => e.description(),
            Error::Custom(ref e) => e,
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Lib(ref e) => Some(e),
            Error::Clap(ref e) => Some(e),
            Error::Custom(_) => None,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Lib(ref e) => error::Error::description(e).fmt(f),
            Error::Clap(ref e) => error::Error::description(e).fmt(f),
            Error::Custom(ref e) => e.fmt(f),
        }
    }
}

impl From<mp::Error> for Error {
    fn from(e: mp::Error) -> Self {
        Error::Lib(e)
    }
}

impl From<clap::Error> for Error {
    fn from(e: clap::Error) -> Self {
        Error::Clap(e)
    }
}

pub fn parse<I, S>(args: I) -> Result
    where I: IntoIterator<Item = S>,
          S: Clone,
          ::std::ffi::OsString: From<S>
{
    let app = App::new("mprovision")
        .about("A tool that helps iOS developers to manage mobileprovision files.")
        .subcommand(SubCommand::with_name("list")
            .arg(Arg::with_name("TEXT")
                .long("--filter")
                .required(false)
                .empty_values(false)
                .takes_value(true))
            .arg(Arg::with_name("DAYS")
                .long("--expires-in-days")
                .required(false)
                .empty_values(false)
                .takes_value(true))
            .arg(Arg::with_name("DIRECTORY")
                .required(false)
                .empty_values(false)
                .takes_value(true)))
        .subcommand(SubCommand::with_name("cleanup").arg(Arg::with_name("DIRECTORY")
            .required(false)
            .empty_values(false)
            .takes_value(true)));

    let matches = app.get_matches_from_safe(args)?;
    if let Some(list_matches) = matches.subcommand_matches("list") {
        let mut params = ListParams::default();
        params.filter = list_matches.value_of("TEXT").map(|text| text.to_string());
        if let Some(days) = list_matches.value_of("DAYS")
            .and_then(|days| days.parse::<i64>().ok()) {
            if days < 0 || days > 365 {
                return Err(Error::Custom("DAYS should be between 0 and 365".to_string()));
            }
            params.expires_in_days = Some(days);
        }
        params.directory = list_matches.value_of("DIRECTORY").map(|dir| dir.into());
        Ok(Command::List(params))
    } else if let Some(cleanup_matches) = matches.subcommand_matches("cleanup") {
        let directory = cleanup_matches.value_of("DIRECTORY").map(|dir| dir.into());
        Ok(Command::Cleanup(directory))
    } else {
        Err(Error::Custom("Command isn't implemented".to_string()))
    }
}

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

    #[test]
    fn list_command() {
        expect!(parse(&["mprovision", "list"]))
            .to(be_ok().value(Command::List(ListParams::default())));

        expect!(parse(&["mprovision", "list", "."])).to(be_ok().value(Command::List(ListParams {
            filter: None,
            expires_in_days: None,
            directory: Some(".".into()),
        })));

        expect!(parse(&["mprovision", "list", "--filter", "abc"]))
            .to(be_ok().value(Command::List(ListParams {
                filter: Some("abc".to_string()),
                expires_in_days: None,
                directory: None,
            })));

        expect!(parse(&["mprovision", "list", "--filter", ""])).to(be_err());

        expect!(parse(&["mprovision", "list", "--expires-in-days", "3"]))
            .to(be_ok().value(Command::List(ListParams {
                filter: None,
                expires_in_days: Some(3),
                directory: None,
            })));

        expect!(parse(&["mprovision", "list", "--expires-in-days", "-3"])).to(be_err());
        expect!(parse(&["mprovision", "list", "--expires-in-days", "366"])).to(be_err());

        expect!(parse(&["mprovision", "list", "--filter", "abc", "--expires-in-days", "3", "."]))
            .to(be_ok().value(Command::List(ListParams {
                filter: Some("abc".to_string()),
                expires_in_days: Some(3),
                directory: Some(".".into()),
            })));
    }

    #[test]
    fn cleanup_command() {
        expect!(parse(&["mprovision", "cleanup"])).to(be_ok().value(Command::Cleanup(None)));

        expect!(parse(&["mprovision", "cleanup", "."]))
            .to(be_ok().value(Command::Cleanup(Some(".".into()))));
    }
}
<commit_msg>Add about info for both subcommands<commit_after>use clap::{self, Arg, App, SubCommand};
use std::io::{self, Write};
use std::process;
use std::path::PathBuf;
use std::error;
use std::result;
use std::fmt;
use mprovision as mp;

#[derive(Debug, PartialEq)]
pub enum Command {
    List(ListParams),
    Cleanup(Option<PathBuf>),
}

#[derive(Debug, Default, PartialEq)]
pub struct ListParams {
    pub filter: Option<String>,
    pub expires_in_days: Option<i64>,
    pub directory: Option<PathBuf>,
}

pub type Result = result::Result<Command, Error>;

#[derive(Debug)]
pub enum Error {
    Lib(mp::Error),
    Clap(clap::Error),
    Custom(String),
}

impl Error {
    pub fn exit(&self) -> ! {
        match *self {
            Error::Clap(ref e) => e.exit(),
            _ => {
                writeln!(&mut io::stderr(), "{}", self).unwrap();
                process::exit(1);
            }
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Lib(ref e) => e.description(),
            Error::Clap(ref e) => e.description(),
            Error::Custom(ref e) => e,
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Lib(ref e) => Some(e),
            Error::Clap(ref e) => Some(e),
            Error::Custom(_) => None,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Lib(ref e) => error::Error::description(e).fmt(f),
            Error::Clap(ref e) => error::Error::description(e).fmt(f),
            Error::Custom(ref e) => e.fmt(f),
        }
    }
}

impl From<mp::Error> for Error {
    fn from(e: mp::Error) -> Self {
        Error::Lib(e)
    }
}

impl From<clap::Error> for Error {
    fn from(e: clap::Error) -> Self {
        Error::Clap(e)
    }
}

pub fn parse<I, S>(args: I) -> Result
    where I: IntoIterator<Item = S>,
          S: Clone,
          ::std::ffi::OsString: From<S>
{
    let app = App::new("mprovision")
        .about("A tool that helps iOS developers to manage mobileprovision files.")
        .subcommand(SubCommand::with_name("list")
            .about("Lists provisioning profiles")
            .arg(Arg::with_name("TEXT")
                .long("--filter")
                .required(false)
                .empty_values(false)
                .takes_value(true))
            .arg(Arg::with_name("DAYS")
                .long("--expires-in-days")
                .required(false)
                .empty_values(false)
                .takes_value(true))
            .arg(Arg::with_name("DIRECTORY")
                .required(false)
                .empty_values(false)
                .takes_value(true)))
        .subcommand(SubCommand::with_name("cleanup")
            .about("Removes expired provisioning profiles")
            .arg(Arg::with_name("DIRECTORY")
                .required(false)
                .empty_values(false)
                .takes_value(true)));

    let matches = app.get_matches_from_safe(args)?;
    if let Some(list_matches) = matches.subcommand_matches("list") {
        let mut params = ListParams::default();
        params.filter = list_matches.value_of("TEXT").map(|text| text.to_string());
        if let Some(days) = list_matches.value_of("DAYS")
            .and_then(|days| days.parse::<i64>().ok()) {
            if days < 0 || days > 365 {
                return Err(Error::Custom("DAYS should be between 0 and 365".to_string()));
            }
            params.expires_in_days = Some(days);
        }
        params.directory = list_matches.value_of("DIRECTORY").map(|dir| dir.into());
        Ok(Command::List(params))
    } else if let Some(cleanup_matches) = matches.subcommand_matches("cleanup") {
        let directory = cleanup_matches.value_of("DIRECTORY").map(|dir| dir.into());
        Ok(Command::Cleanup(directory))
    } else {
        Err(Error::Custom("Command isn't implemented".to_string()))
    }
}

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

    #[test]
    fn list_command() {
        expect!(parse(&["mprovision", "list"]))
            .to(be_ok().value(Command::List(ListParams::default())));

        expect!(parse(&["mprovision", "list", "."])).to(be_ok().value(Command::List(ListParams {
            filter: None,
            expires_in_days: None,
            directory: Some(".".into()),
        })));

        expect!(parse(&["mprovision", "list", "--filter", "abc"]))
            .to(be_ok().value(Command::List(ListParams {
                filter: Some("abc".to_string()),
                expires_in_days: None,
                directory: None,
            })));

        expect!(parse(&["mprovision", "list", "--filter", ""])).to(be_err());

        expect!(parse(&["mprovision", "list", "--expires-in-days", "3"]))
            .to(be_ok().value(Command::List(ListParams {
                filter: None,
                expires_in_days: Some(3),
                directory: None,
            })));

        expect!(parse(&["mprovision", "list", "--expires-in-days", "-3"])).to(be_err());
        expect!(parse(&["mprovision", "list", "--expires-in-days", "366"])).to(be_err());

        expect!(parse(&["mprovision", "list", "--filter", "abc", "--expires-in-days", "3", "."]))
            .to(be_ok().value(Command::List(ListParams {
                filter: Some("abc".to_string()),
                expires_in_days: Some(3),
                directory: Some(".".into()),
            })));
    }

    #[test]
    fn cleanup_command() {
        expect!(parse(&["mprovision", "cleanup"])).to(be_ok().value(Command::Cleanup(None)));

        expect!(parse(&["mprovision", "cleanup", "."]))
            .to(be_ok().value(Command::Cleanup(Some(".".into()))));
    }
}
<|endoftext|>


<commit_before>use super::*;
// use cached_tree_hash::CachedTreeHash;
// use ssz::{Decodable, Encodable};
// use tree_hash::TreeHash;

impl<T, N: Unsigned> tree_hash::TreeHash for FixedLenVec<T, N>
where
    T: tree_hash::TreeHash,
{
    fn tree_hash_type() -> tree_hash::TreeHashType {
        tree_hash::TreeHashType::Vector
    }

    fn tree_hash_packed_encoding(&self) -> Vec<u8> {
        unreachable!("Vector should never be packed.")
    }

    fn tree_hash_packing_factor() -> usize {
        unreachable!("Vector should never be packed.")
    }

    fn tree_hash_root(&self) -> Vec<u8> {
        tree_hash::impls::vec_tree_hash_root(&self.vec)
    }
}

impl<T, N: Unsigned> cached_tree_hash::CachedTreeHash for FixedLenVec<T, N>
where
    T: cached_tree_hash::CachedTreeHash + tree_hash::TreeHash,
{
    fn new_tree_hash_cache(
        &self,
        depth: usize,
    ) -> Result<cached_tree_hash::TreeHashCache, cached_tree_hash::Error> {
        let (cache, _overlay) = cached_tree_hash::vec::new_tree_hash_cache(&self.vec, depth)?;

        Ok(cache)
    }

    fn tree_hash_cache_schema(&self, depth: usize) -> cached_tree_hash::BTreeSchema {
        cached_tree_hash::vec::produce_schema(&self.vec, depth)
    }

    fn update_tree_hash_cache(
        &self,
        cache: &mut cached_tree_hash::TreeHashCache,
    ) -> Result<(), cached_tree_hash::Error> {
        cached_tree_hash::vec::update_tree_hash_cache(&self.vec, cache)?;

        Ok(())
    }
}

impl<T, N: Unsigned> ssz::Encodable for FixedLenVec<T, N>
where
    T: ssz::Encodable,
{
    fn is_ssz_fixed_len() -> bool {
        true
    }

    fn ssz_append(&self, buf: &mut Vec<u8>) {
        if T::is_ssz_fixed_len() {
            buf.reserve(T::ssz_fixed_len() * self.len());

            for item in &self.vec {
                item.ssz_append(buf);
            }
        } else {
            let mut encoder = ssz::SszEncoder::list(buf, self.len() * ssz::BYTES_PER_LENGTH_OFFSET);

            for item in &self.vec {
                encoder.append(item);
            }

            encoder.finalize();
        }
    }
}

impl<T, N: Unsigned> ssz::Decodable for FixedLenVec<T, N>
where
    T: ssz::Decodable + Default,
{
    fn is_ssz_fixed_len() -> bool {
        T::is_ssz_fixed_len()
    }

    fn ssz_fixed_len() -> usize {
        if <Self as ssz::Decodable>::is_ssz_fixed_len() {
            T::ssz_fixed_len() * N::to_usize()
        } else {
            ssz::BYTES_PER_LENGTH_OFFSET
        }
    }

    fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, ssz::DecodeError> {
        if bytes.len() == 0 {
            Ok(FixedLenVec::from(vec![]))
        } else if T::is_ssz_fixed_len() {
            bytes
                .chunks(T::ssz_fixed_len())
                .map(|chunk| T::from_ssz_bytes(chunk))
                .collect::<Result<Vec<T>, _>>()
                .and_then(|vec| Ok(vec.into()))
        } else {
            ssz::decode_list_of_variable_length_items(bytes).and_then(|vec| Ok(vec.into()))
        }
    }
}
<commit_msg>Add tests for fixed_len_vec ssz<commit_after>use super::*;
// use cached_tree_hash::CachedTreeHash;
// use ssz::{Decodable, Encodable};
// use tree_hash::TreeHash;

impl<T, N: Unsigned> tree_hash::TreeHash for FixedLenVec<T, N>
where
    T: tree_hash::TreeHash,
{
    fn tree_hash_type() -> tree_hash::TreeHashType {
        tree_hash::TreeHashType::Vector
    }

    fn tree_hash_packed_encoding(&self) -> Vec<u8> {
        unreachable!("Vector should never be packed.")
    }

    fn tree_hash_packing_factor() -> usize {
        unreachable!("Vector should never be packed.")
    }

    fn tree_hash_root(&self) -> Vec<u8> {
        tree_hash::impls::vec_tree_hash_root(&self.vec)
    }
}

impl<T, N: Unsigned> cached_tree_hash::CachedTreeHash for FixedLenVec<T, N>
where
    T: cached_tree_hash::CachedTreeHash + tree_hash::TreeHash,
{
    fn new_tree_hash_cache(
        &self,
        depth: usize,
    ) -> Result<cached_tree_hash::TreeHashCache, cached_tree_hash::Error> {
        let (cache, _overlay) = cached_tree_hash::vec::new_tree_hash_cache(&self.vec, depth)?;

        Ok(cache)
    }

    fn tree_hash_cache_schema(&self, depth: usize) -> cached_tree_hash::BTreeSchema {
        cached_tree_hash::vec::produce_schema(&self.vec, depth)
    }

    fn update_tree_hash_cache(
        &self,
        cache: &mut cached_tree_hash::TreeHashCache,
    ) -> Result<(), cached_tree_hash::Error> {
        cached_tree_hash::vec::update_tree_hash_cache(&self.vec, cache)?;

        Ok(())
    }
}

impl<T, N: Unsigned> ssz::Encodable for FixedLenVec<T, N>
where
    T: ssz::Encodable,
{
    fn is_ssz_fixed_len() -> bool {
        true
    }

    fn ssz_append(&self, buf: &mut Vec<u8>) {
        if T::is_ssz_fixed_len() {
            buf.reserve(T::ssz_fixed_len() * self.len());

            for item in &self.vec {
                item.ssz_append(buf);
            }
        } else {
            let mut encoder = ssz::SszEncoder::list(buf, self.len() * ssz::BYTES_PER_LENGTH_OFFSET);

            for item in &self.vec {
                encoder.append(item);
            }

            encoder.finalize();
        }
    }
}

impl<T, N: Unsigned> ssz::Decodable for FixedLenVec<T, N>
where
    T: ssz::Decodable + Default,
{
    fn is_ssz_fixed_len() -> bool {
        T::is_ssz_fixed_len()
    }

    fn ssz_fixed_len() -> usize {
        if <Self as ssz::Decodable>::is_ssz_fixed_len() {
            T::ssz_fixed_len() * N::to_usize()
        } else {
            ssz::BYTES_PER_LENGTH_OFFSET
        }
    }

    fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, ssz::DecodeError> {
        if bytes.len() == 0 {
            Ok(FixedLenVec::from(vec![]))
        } else if T::is_ssz_fixed_len() {
            bytes
                .chunks(T::ssz_fixed_len())
                .map(|chunk| T::from_ssz_bytes(chunk))
                .collect::<Result<Vec<T>, _>>()
                .and_then(|vec| Ok(vec.into()))
        } else {
            ssz::decode_list_of_variable_length_items(bytes).and_then(|vec| Ok(vec.into()))
        }
    }
}

#[cfg(test)]
mod ssz_tests {
    use super::*;
    use ssz::*;
    use typenum::*;

    #[test]
    fn encode() {
        let vec: FixedLenVec<u16, U2> = vec![0; 2].into();
        assert_eq!(vec.as_ssz_bytes(), vec![0, 0, 0, 0]);
        assert_eq!(<FixedLenVec<u16, U2> as Encodable>::ssz_fixed_len(), 4);
    }

    fn round_trip<T: Encodable + Decodable + std::fmt::Debug + PartialEq>(item: T) {
        let encoded = &item.as_ssz_bytes();
        dbg!(encoded);
        assert_eq!(T::from_ssz_bytes(&encoded), Ok(item));
    }

    #[test]
    fn u16_len_8() {
        round_trip::<FixedLenVec<u16, U8>>(vec![42; 8].into());
        round_trip::<FixedLenVec<u16, U8>>(vec![0; 8].into());
    }
}
<|endoftext|>


<commit_before>#![cfg(rayon_unstable)]

use super::Scope;
use internal::task::{ScopeHandle, Task, ToScopeHandle};
use std::any::Any;
use std::mem;
use std::sync::Arc;

impl<'scope> ToScopeHandle<'scope> for Scope<'scope> {
    type ScopeHandle = LocalScopeHandle<'scope>;

    fn to_scope_handle(&self) -> Self::ScopeHandle {
        unsafe { LocalScopeHandle::new(self) }
    }
}

#[derive(Debug)]
pub struct LocalScopeHandle<'scope> {
    scope: *const Scope<'scope>,
}

impl<'scope> LocalScopeHandle<'scope> {
    /// Caller guarantees that `*scope` will remain valid
    /// until the scope completes. Since we acquire a ref,
    /// that means it will remain valid until we release it.
    unsafe fn new(scope: &Scope<'scope>) -> Self {
        scope.job_completed_latch.increment();
        LocalScopeHandle { scope: scope }
    }
}

impl<'scope> Drop for LocalScopeHandle<'scope> {
    fn drop(&mut self) {
        unsafe {
            if !self.scope.is_null() {
                (*self.scope).job_completed_ok();
            }
        }
    }
}

/// We assert that the `Self` type remains valid until a
/// method is called, and that `'scope` will not end until
/// that point.
unsafe impl<'scope> ScopeHandle<'scope> for LocalScopeHandle<'scope> {
    unsafe fn spawn_task<T: Task + 'scope>(&self, task: Arc<T>) {
        let scope = &*self.scope;
        scope.registry.submit_task(task);
    }

    fn ok(self) {
        mem::drop(self);
    }

    fn panicked(self, err: Box<Any + Send>) {
        unsafe {
            (*self.scope).job_panicked(err);
            mem::forget(self); // no need to run dtor now
        }
    }
}
<commit_msg>fix ToScopeHandle for ScopeBase<commit_after>#![cfg(rayon_unstable)]

use super::{Scope, ScopeBase};
use internal::task::{ScopeHandle, Task, ToScopeHandle};
use std::any::Any;
use std::mem;
use std::sync::Arc;

impl<'scope> ToScopeHandle<'scope> for Scope<'scope> {
    type ScopeHandle = LocalScopeHandle<'scope>;

    fn to_scope_handle(&self) -> Self::ScopeHandle {
        unsafe { LocalScopeHandle::new(self) }
    }
}

#[derive(Debug)]
pub struct LocalScopeHandle<'scope> {
    scope: *const ScopeBase<'scope>,
}

impl<'scope> LocalScopeHandle<'scope> {
    /// Caller guarantees that `*scope` will remain valid
    /// until the scope completes. Since we acquire a ref,
    /// that means it will remain valid until we release it.
    unsafe fn new(scope: &Scope<'scope>) -> Self {
        scope.base.increment();
        LocalScopeHandle { scope: &scope.base }
    }
}

impl<'scope> Drop for LocalScopeHandle<'scope> {
    fn drop(&mut self) {
        unsafe {
            if !self.scope.is_null() {
                (*self.scope).job_completed_ok();
            }
        }
    }
}

/// We assert that the `Self` type remains valid until a
/// method is called, and that `'scope` will not end until
/// that point.
unsafe impl<'scope> ScopeHandle<'scope> for LocalScopeHandle<'scope> {
    unsafe fn spawn_task<T: Task + 'scope>(&self, task: Arc<T>) {
        let scope = &*self.scope;
        scope.registry.submit_task(task);
    }

    fn ok(self) {
        mem::drop(self);
    }

    fn panicked(self, err: Box<Any + Send>) {
        unsafe {
            (*self.scope).job_panicked(err);
            mem::forget(self); // no need to run dtor now
        }
    }
}
<|endoftext|>


<commit_before>// Kevin Cantu
// Boyer-Moore string searching

use std;

// Function: findn_str_between
//
// Boyer-Moore string search, which returns
// up to `nn` byte positions of matched substrings
fn findn_str_between (haystack: str, needle: str, nn: uint,
                      start: uint, end: uint) -> [uint] {

   let results = [];

   let nlen = str::len(needle);
   let hlen = str::len(haystack);

   // empty haystack
   if hlen == 0u {
      ret results;
   }

   // empty needle
   if nlen == 0u {
      vec::push(results, 0u);
      ret results;
   }

   // needle too large
   if hlen < nlen {
      ret results;
   }

   // generate the tables
   let ct = char_table(needle);
   let pt = prefix_table(needle);

   // simplify the table referencing
   let getShift = fn@(pos: uint) -> uint {
/*
      assert needle != "";
      assert 0u <= pos;
      assert       pos < nlen;
*/
      let charShift = ct[needle[pos] as uint];
      let prefShift = pt[nlen - pos];

      if charShift > prefShift {
         ret charShift;
      } else {
         ret prefShift;
      }
   };

   // step up through the haystack
   let outerii = start;
   while outerii < end - nlen + 1u {

      // step back through needle
      let windowii = nlen;
      while 0u < windowii
            && (outerii + windowii - 1u) < hlen  // don't exceed haystack
      {
         windowii -= 1u;

         //std::io::println(#fmt("%02x.@%u =? %02x.@%u",
         //                 needle[windowii] as uint,
         //                 windowii,
         //                 haystack[outerii+windowii] as uint,
         //                 outerii + windowii));

         // if still matching
         if needle[windowii] == haystack[outerii+windowii] {

            // if full match
            if windowii == 0u {
               //std::io::println(#fmt("[pushing %u]", outerii));
               vec::push(results, outerii);

               if vec::len(results) >= nn {
                  ret results;
               } else {
                  outerii += nlen;
               }
            }
         } else {
            outerii +=
               if windowii == nlen - 1u {
                  // not matching yet
                  1u
               } else {
                  // was partial match
                  getShift(nlen - windowii)
               };

            break;
         }
      }
   }

   ret results;
}

fn char_table (needle: str) -> [uint] {
   let len = str::len(needle);
   let mm  = vec::init_elt_mut(256u, len);

   let jj = len - 1u; // drop the last byte

   assert jj >= 0u;
   assert jj < str::len(needle);

   // from last-1 to first
   while jj > 0u {
      jj -= 1u;

      let key = needle[jj] as uint;

      // if we haven't set it yet, set it now
      // (besides default)
      if mm[key] == len {
         mm[key] = len - 1u - jj;
      }
   }

   ret vec::from_mut(mm);
}

fn prefix_table (needle: str) -> [uint] {
   let needle_ = str::bytes(needle);

   let lim   = vec::len(needle_);
   assert 0u < lim;

   let mm  = vec::init_elt_mut(lim, lim); // FIXME: is this an OK default?

   // step to larger suffixes
   let sii = 0u;
   while sii < lim {

      // tail of the needle we seek
      let suffix      = vec::slice(needle_, lim - sii,      lim);
      let suffix_plus = vec::slice(needle_, lim - sii - 1u, lim);
      let slen = vec::len(suffix);

      // step to smaller prefixes
      let pii = lim - 1u;
      while pii > 0u {

         // a prefix of the needle that might be matched by
         // a partial match of a suffix
         // (which we might want to jump to)
         let prefix = vec::slice(needle_, 0u, pii);
         let plen = vec::len(prefix);

         //let msg  = "<"+suffix+"("+#fmt("%u",sii)+")";
         //let msg2 = prefix+"("+#fmt("%u",pii)+")>";
         //let msg  = "<suf("+#fmt("%u",sii)+")";
         //let msg2 = "pref("+#fmt("%u",pii)+")>";
         //std::io::println(msg + " × " + msg2);

         // suffix might be fully matched
         let is_suffix_matched =
            vec::ends_with(prefix, suffix)
            && !vec::ends_with(prefix, suffix_plus)
            &&  slen < plen;

         // prefix is bigger than suffix, only tail can match
         let is_suffix_partially_matched =
            plen <= slen
            && vec::ends_with(suffix, prefix);

         if is_suffix_matched || is_suffix_partially_matched {
            // if we haven't set it yet, set it now
            // (besides default)
            if mm[sii] == lim {
               mm[sii] = lim-pii;
               //std::io::println(#fmt("%u => %u", kk, vv));
            }
         }

         pii -= 1u;
      }

      // no matching prefix
      // if we haven't set it yet, set it now
      // (besides default)
      if mm[sii] == lim {
         mm[sii] = lim-pii;
         //std::io::println(#fmt("%u => %u", kk, vv));
      }

      sii += 1u;
   }

   ret vec::from_mut(mm);
}

#[test]
fn test_char_table () {
   let ct = char_table("ANPANMAN");
   assert 1u == ct['A' as uint];
   assert 2u == ct['M' as uint];
   assert 3u == ct['N' as uint];
   assert 5u == ct['P' as uint];
   assert str::len("ANPANMAN") == ct['z' as uint];
}

#[test]
fn test_prefix_table_ascii() {
   let pt = prefix_table("ANPANMAN");
                            //      ... 8

   assert 1u == pt[0u]; //        (n)
   assert 8u == pt[1u]; //       (a)n
   assert 3u == pt[2u]; //      (m)an
   assert 6u == pt[3u]; //     (n)man
   assert 6u == pt[4u]; //    (a)nman
   assert 6u == pt[5u]; //   (p)anman
   assert 6u == pt[6u]; //  (n)panman
   assert 6u == pt[7u]; // (a)npanman
   //assert 0u == pt.get(8u); // fail
}

#[test]
fn test_prefix_table_utf8() {
   let pt = prefix_table("ประเ");

   assert  1u == pt[0u];
   assert 12u == pt[3u];
   assert 12u == pt[6u];
   assert 12u == pt[9u];
}

fn findn_str(haystack: str, needle: str, nn: uint) -> [uint] {
   findn_str_between(haystack, needle, nn, 0u, str::len(haystack))
}

fn find_str_(haystack: str, needle: str) -> option<uint> {
   let found = findn_str(haystack, needle, 1u);

   alt vec::len(found) {
      0u { option::none }
      xx { option::some(found[0u]) }
   }
}

#[test]
fn test_findn_str() {
   assert [] == findn_str("banana", "apple pie", 1u);
   assert (findn_str("abcxxxxxx", "abc", 1u) == [0u]);
   assert (findn_str("xxxabcxxx", "abc", 1u) == [3u]);
   assert (findn_str("xxxxxxabc", "abc", 1u) == [6u]);
   assert (findn_str("xxxabcabc", "abc", 1u) == [3u]);
   assert (findn_str("xxxabcabc", "abc", 5u) == [3u, 6u]);
   assert (findn_str("xxxabcxabc", "abc", 5u) == [3u, 7u]);
   assert (findn_str("xxxabcxxabc", "abc", 5u) == [3u, 8u]);
}

#[test]
fn test_find_strX_ascii() {
  assert (find_str_("banana", "apple pie") == option::none);
  assert (find_str_("", "") == option::none);
  assert (find_str_("abcxxxxxx", "abc") == option::some(0u));
  assert (find_str_("xxxabcxxx", "abc") == option::some(3u));
  assert (find_str_("xxxxxxabc", "abc") == option::some(6u));
}

#[test]
fn test_find_strX_utf8() {
  let data = "ประเทศไทย中华Việt Nam";
  assert (find_str_(data, "ไท华") == option::none);
  assert (find_str_(data, "")     == option::some( 0u));
  assert (find_str_(data, "ประเ") == option::some( 0u));
  assert (find_str_(data, "ะเ")   == option::some( 6u));
  assert (find_str_(data, "ระ") == option::some(3u));
  assert (find_str_(data, "ศไทย中华") == option::some(15u));
  assert (find_str_(data, "ไทย中华") == option::some(18u));
  assert (find_str_(data, "ย中华") == option::some(24u));
  assert (find_str_(data, "中华") == option::some(27u));
}

<commit_msg>getting the shifts straightened out...<commit_after>// Kevin Cantu
// Boyer-Moore string searching

use std;

// Function: findn_str_between
//
// Boyer-Moore string search, which returns
// up to `nn` byte positions of matched substrings
fn findn_str_between (haystack: str, needle: str, nn: uint,
                      start: uint, end: uint) -> [uint] {

   let results = [];

   let nlen = str::len(needle);
   let hlen = str::len(haystack);

   // empty haystack
   if hlen == 0u {
      ret results;
   }

   // empty needle
   if nlen == 0u {
      vec::push(results, 0u);
      ret results;
   }

   // needle too large
   if hlen < nlen {
      ret results;
   }

   // generate the tables
   let ct = char_table(needle);
   let pt = prefix_table(needle);

   // simplify the table referencing
   let getShift = fn@(pos: uint) -> uint {
/*
      assert needle != "";
      assert 0u <= pos;
      assert       pos < nlen;
*/
      let charShift = ct[needle[pos] as uint];
      let prefShift = pt[nlen - pos];

      std::io::println(#fmt("<c%u p%u>", charShift, prefShift));

      if charShift > prefShift {
         ret charShift;
      } else {
         ret prefShift;
      }
   };

   let getCharShift = fn@(pos: uint) -> uint {
      let charShift = ct[needle[pos] as uint];
      std::io::println(#fmt("<c%u>", charShift));

      ret charShift;
   };

   // step up through the haystack
   let outerii = start;
   while outerii < end - nlen + 1u {

      // step back through needle
      let windowii = nlen;
      while 0u < windowii
            && (outerii + windowii - 1u) < hlen  // don't exceed haystack
      {
         windowii -= 1u;

         //std::io::println(#fmt("%02x.@%u =? %02x.@%u",
         //                 needle[windowii] as uint,
         //                 windowii,
         //                 haystack[outerii+windowii] as uint,
         //                 outerii + windowii));

         // if still matching
         if needle[windowii] == haystack[outerii+windowii] {

            // if full match
            if windowii == 0u {
               std::io::println(#fmt("[pushing %u]", outerii));
               vec::push(results, outerii);

               if vec::len(results) >= nn {
                  ret results;
               } else {
                  outerii += nlen;
               }
            }
         } else {
            outerii +=
               if windowii == nlen - 1u {
                  // not matching yet
                  //getCharShift(nlen - windowii)
                  // PENDING: is this offset wrong?
                  //          Why does it always return 4 in the utf8_B test?
                  getCharShift(nlen - windowii)
               } else {
                  // was partial match
                  getShift(nlen - windowii)
               };

            break;
         }
      }
   }

   ret results;
}

fn char_table (needle: str) -> [uint] {
   let len = str::len(needle);
   let mm  = vec::init_elt_mut(255u, len);

   let jj = len - 1u; // drop the last byte

   assert jj >= 0u;
   assert jj < str::len(needle);

   // from last-1 to first
   while jj > 0u {
      jj -= 1u;

      let key = needle[jj] as uint;

      // if we haven't set it yet, set it now
      // (besides default)
      if mm[key] == len {
         mm[key] = len - 1u - jj;
      }
   }

   ret vec::from_mut(mm);
}

fn prefix_table (needle: str) -> [uint] {
   let needle_ = str::bytes(needle);

   let lim   = vec::len(needle_);
   assert 0u < lim;

   let mm  = vec::init_elt_mut(lim, lim); // FIXME: is this an OK default?

   // step to larger suffixes
   let sii = 0u;
   while sii < lim {

      // tail of the needle we seek
      let suffix      = vec::slice(needle_, lim - sii,      lim);
      let suffix_plus = vec::slice(needle_, lim - sii - 1u, lim);
      let slen = vec::len(suffix);

      // step to smaller prefixes
      let pii = lim - 1u;
      while pii > 0u {

         // a prefix of the needle that might be matched by
         // a partial match of a suffix
         // (which we might want to jump to)
         let prefix = vec::slice(needle_, 0u, pii);
         let plen = vec::len(prefix);

         //let msg  = "<"+suffix+"("+#fmt("%u",sii)+")";
         //let msg2 = prefix+"("+#fmt("%u",pii)+")>";
         //let msg  = "<suf("+#fmt("%u",sii)+")";
         //let msg2 = "pref("+#fmt("%u",pii)+")>";
         //std::io::println(msg + " × " + msg2);

         // suffix might be fully matched
         let is_suffix_matched =
            vec::ends_with(prefix, suffix)
            && !vec::ends_with(prefix, suffix_plus)
            &&  slen < plen;

         // prefix is bigger than suffix, only tail can match
         let is_suffix_partially_matched =
            plen <= slen
            && vec::ends_with(suffix, prefix);

         if is_suffix_matched || is_suffix_partially_matched {
            // if we haven't set it yet, set it now
            // (besides default)
            if mm[sii] == lim {
               mm[sii] = lim-pii;
               //std::io::println(#fmt("%u => %u", kk, vv));
            }
         }

         pii -= 1u;
      }

      // no matching prefix
      // if we haven't set it yet, set it now
      // (besides default)
      if mm[sii] == lim {
         mm[sii] = lim-pii;
         //std::io::println(#fmt("%u => %u", kk, vv));
      }

      sii += 1u;
   }

   ret vec::from_mut(mm);
}

//#[test]
fn test_char_table () {
   let ct = char_table("ANPANMAN");
   assert 1u == ct['A' as uint];
   assert 2u == ct['M' as uint];
   assert 3u == ct['N' as uint];
   assert 5u == ct['P' as uint];
   assert str::len("ANPANMAN") == ct['z' as uint];
}

//#[test]
fn test_prefix_table_ascii() {
   let pt = prefix_table("ANPANMAN");
                            //      ... 8

   assert 1u == pt[0u]; //        (n)
   assert 8u == pt[1u]; //       (a)n
   assert 3u == pt[2u]; //      (m)an
   assert 6u == pt[3u]; //     (n)man
   assert 6u == pt[4u]; //    (a)nman
   assert 6u == pt[5u]; //   (p)anman
   assert 6u == pt[6u]; //  (n)panman
   assert 6u == pt[7u]; // (a)npanman
   //assert 0u == pt.get(8u); // fail
}

//#[test]
fn test_prefix_table_utf8() {
   let pt = prefix_table("ประเ");

   assert  1u == pt[0u];
   assert 12u == pt[3u];
   assert 12u == pt[6u];
   assert 12u == pt[9u];
}

fn findn_str(haystack: str, needle: str, nn: uint) -> [uint] {
   findn_str_between(haystack, needle, nn, 0u, str::len(haystack))
}

fn find_str_(haystack: str, needle: str) -> option<uint> {
   let found = findn_str(haystack, needle, 1u);

   alt vec::len(found) {
      0u { option::none }
      xx { option::some(found[0u]) }
   }
}

//#[test]
fn test_findn_str() {
   assert [] == findn_str("banana", "apple pie", 1u);
   assert (findn_str("abcxxxxxx", "abc", 1u) == [0u]);
   assert (findn_str("xxxabcxxx", "abc", 1u) == [3u]);
   assert (findn_str("xxxxxxabc", "abc", 1u) == [6u]);
   assert (findn_str("xxxabcabc", "abc", 1u) == [3u]);
   assert (findn_str("xxxabcabc", "abc", 5u) == [3u, 6u]);
   assert (findn_str("xxxabcxabc", "abc", 5u) == [3u, 7u]);
   assert (findn_str("xxxabcxxabc", "abc", 5u) == [3u, 8u]);
}

//#[test]
fn test_find_strX_ascii() {
  assert (find_str_("banana", "apple pie") == option::none);
  assert (find_str_("", "") == option::none);
  assert (find_str_("abcxxxxxx", "abc") == option::some(0u));
  assert (find_str_("xxxabcxxx", "abc") == option::some(3u));
  assert (find_str_("xxxxxxabc", "abc") == option::some(6u));
}

//#[test]
fn test_find_strX_utf8() {
  let data = "ประเทศไทย中华Việt Nam";
  assert (find_str_(data, "ไท华") == option::none);
  assert (find_str_(data, "")     == option::some( 0u));
  assert (find_str_(data, "ประเ") == option::some( 0u));
  assert (find_str_(data, "ระ") == option::some(3u));
  assert (find_str_(data, "ย中华") == option::some(24u));
}

#[test]
fn test_find_strX_utf8_B() {
// PENDING
   let data = "ประเทศไทย中华Việt Nam";
   assert (find_str_(data, "ะเ")   == option::some( 6u));  // why does this shift 4 so much?
   assert (find_str_(data, "ศไทย中华") == option::some(15u));
   assert (find_str_(data, "ไทย中华") == option::some(18u));
   assert (find_str_(data, "中华") == option::some(27u));
}

#[test]
fn hmm() {
   let ct = char_table("ะเ"); //e0b8b0 e0b980
   assert 2u == ct[0x_e0_u];
   assert 4u == ct[0x_b8_u];
   assert 3u == ct[0x_b0_u];
   assert 2u == ct[0x_e0_u];
   assert 1u == ct[0x_b9_u];
   assert 6u == ct[0x_80_u];

   assert 6u == ct["ะเ"[5u]]
}

<|endoftext|>


<commit_before>use cookie::{CookieJar};

pub trait Cookies {
    fn find_cookie_jar(&self) -> Option<&CookieJar<'static>>;
    fn store_cookie_jar(&mut self, jar: CookieJar<'static>);
    fn cookies<'a>(&'a mut self, key: &[u8]) -> &'a CookieJar {
        let has_jar = { self.find_cookie_jar().is_some() };

        if !has_jar {
            let jar = CookieJar::new(key);
            self.store_cookie_jar(jar);
        }

        self.find_cookie_jar().unwrap()
    }
}

// impl Cookies for Request {
//     fn find_cookie_jar(&self) -> Option<&CookieJar<'static>> {
//         self.ext().find()
//     }

//     fn store_cookie_jar(&mut self, jar: CookieJar<'static>) {
//         self.ext_mut().insert(jar);
//     }
// }<commit_msg>refactor: uncomment Cookies body<commit_after>use cookie::{CookieJar};
use server::Request;

pub trait Cookies {
    fn find_cookie_jar(&self) -> Option<&CookieJar<'static>>;
    fn store_cookie_jar(&mut self, jar: CookieJar<'static>);
    fn cookies<'a>(&'a mut self, key: &[u8]) -> &'a CookieJar {
        let has_jar = { self.find_cookie_jar().is_some() };

        if !has_jar {
            let jar = CookieJar::new(key);
            self.store_cookie_jar(jar);
        }

        self.find_cookie_jar().unwrap()
    }
}

impl Cookies for &'static mut Request {
    fn find_cookie_jar(&self) -> Option<&CookieJar<'static>> {
        self.ext().find()
    }

    fn store_cookie_jar(&mut self, jar: CookieJar<'static>) {
        self.ext_mut().insert(jar);
    }
}<|endoftext|>