<commit_before>#[macro_use] extern crate macrolisp;
use macrolisp::prelude::*;

macro_rules! ck {
    ($left:expr, $right:expr) => {{
        assert_eq!($left, $right);
        $left
    }}
}

#[test]
fn main() {
    let add4 = lisp!(
        (lambda (((a i32)
                  (b i32)
                  (c i32)
                  (d i32))
                 i32)
         (+ a b c d))
    );
    let factorial_proc = lisp!(
        (lambda (((a i32))
                 i32)
         (let ((mut x   a)
                (mut acc 1))
          (while (> x 1)
           (:= acc (* acc x))
           (:= x   (- x 1)))
          acc))
    );
    lisp!(
        (defn factorial (((a i32))
                         i32)
         (if (== a 1)
             1
             (* a (factorial (- a 1)))))
    );

    lisp!(
        (defn factorial_tail (((a i32))
                              i32)
         (defn factorial_tail_helper (((a i32)
                                       (acc i32))
                                      i32)
          (if (== a 1)
              acc
              (factorial_tail_helper (- a 1) (* acc a))))
         (factorial_tail_helper a 1))
    );

    println!("1+2+3+4 = {}", ck!(lisp!( (add4 1 2 3 4)     ), 10)); // TODO example with heterogeneous types
    println!("1-2-3-4 = {}", ck!(lisp!( (- 1 2 3 4)        ), -8));
    println!("5! = {}",      ck!(lisp!( (factorial_proc 5) ), 120));
    println!("6! = {}",      ck!(lisp!( (factorial 6)      ), 720));
    println!("7! = {}",      ck!(lisp!( (factorial_tail 7) ), 5040));
}

#[test]
fn lambdarec_tests() {
    let factorial_rec = lisp!(
        (lambda rec (((a i32))
                      i32)
         (if (== a 1)
             1
             (* a (rec (- a 1)))))
    );
    let fib = lisp!(
        (lambda rec (((a i32))
                      i32)
         (match a
          (0 1)
          (1 1)
          (n (+ (rec (- n 1))
                (rec (- n 2))))))
    );

    println!("-(8!) = {}", ck!(lisp!( (- (factorial_rec 8)) ), -40320));
    lisp!(
        (println! "fib = {} {} {} {} {} {} {} {} {} {} ..." (ck! (fib 0) 1)
                                                            (ck! (fib 1) 1)
                                                            (ck! (fib 2) 2)
                                                            (ck! (fib 3) 3)
                                                            (ck! (fib 4) 5)
                                                            (ck! (fib 5) 8)
                                                            (ck! (fib 6) 13)
                                                            (ck! (fib 7) 21)
                                                            (ck! (fib 8) 34)
                                                            (ck! (fib 9) 55))
    );
}

#[test]
fn lambda_tests() {
    let mut num = 5;
    lisp!(
        (let ((mut add_num (lambda (((x i32))
                                     ())
                             (:= num (+ num x)))))
         (add_num 5))
    );
    println!("num = {}", ck!(num, 10));
}

/* rust-lang/rust#12335

#[test] #[compile_fail]
fn lambdarec_cannot_capture() {
    let mut num = 5;
    lisp!(
        (let ((mut add_num (lambda rec (((x i32))
                                        ())
                            (if (> x 0)
                             (do
                              (:= num (+ num 1))
                              (rec (- x 1)))
                             ()))))
         (add_num 5))
    );
    println!("num = {}", ck!(num, 10));
}
*/

<commit_msg>example of addition with heterogeneous types<commit_after>#[macro_use] extern crate macrolisp;
use macrolisp::prelude::*;

macro_rules! ck {
    ($left:expr, $right:expr) => {{
        assert_eq!($left, $right);
        $left
    }}
}

#[test]
fn main() {
    let add4 = lisp!(
        (lambda (((a i32)
                  (b i32)
                  (c i32)
                  (d i32))
                 i32)
         (+ a b c d))
    );
    let factorial_proc = lisp!(
        (lambda (((a i32))
                 i32)
         (let ((mut x   a)
                (mut acc 1))
          (while (> x 1)
           (:= acc (* acc x))
           (:= x   (- x 1)))
          acc))
    );
    lisp!(
        (defn factorial (((a i32))
                         i32)
         (if (== a 1)
             1
             (* a (factorial (- a 1)))))
    );

    lisp!(
        (defn factorial_tail (((a i32))
                              i32)
         (defn factorial_tail_helper (((a i32)
                                       (acc i32))
                                      i32)
          (if (== a 1)
              acc
              (factorial_tail_helper (- a 1) (* acc a))))
         (factorial_tail_helper a 1))
    );

    struct IntegralFloat { i: i32 }
    impl std::ops::Add for IntegralFloat {
        type Output = f32;
        fn add(self, rhs: Self) -> Self::Output {
            self.i as Self::Output + rhs.i as Self::Output
        }
    }

    println!("1+2+3+4 = {}",  ck!(lisp!( (add4 1 2 3 4)     ),                10));
    println!("1+2+3.0 = {}", ck!(lisp!( (+ (rust { IntegralFloat { i: 1 } })
                                           (rust { IntegralFloat { i: 2 } })
                                           3.0) ),                            6.0));
    println!("1-2-3-4 = {}",  ck!(lisp!( (- 1 2 3 4)        ),                -8));
    println!("5! = {}",       ck!(lisp!( (factorial_proc 5) ),                120));
    println!("6! = {}",       ck!(lisp!( (factorial 6)      ),                720));
    println!("7! = {}",       ck!(lisp!( (factorial_tail 7) ),                5040));
}

#[test]
fn lambdarec_tests() {
    let factorial_rec = lisp!(
        (lambda rec (((a i32))
                      i32)
         (if (== a 1)
             1
             (* a (rec (- a 1)))))
    );
    let fib = lisp!(
        (lambda rec (((a i32))
                      i32)
         (match a
          (0 1)
          (1 1)
          (n (+ (rec (- n 1))
                (rec (- n 2))))))
    );

    println!("-(8!) = {}", ck!(lisp!( (- (factorial_rec 8)) ), -40320));
    lisp!(
        (println! "fib = {} {} {} {} {} {} {} {} {} {} ..." (ck! (fib 0) 1)
                                                            (ck! (fib 1) 1)
                                                            (ck! (fib 2) 2)
                                                            (ck! (fib 3) 3)
                                                            (ck! (fib 4) 5)
                                                            (ck! (fib 5) 8)
                                                            (ck! (fib 6) 13)
                                                            (ck! (fib 7) 21)
                                                            (ck! (fib 8) 34)
                                                            (ck! (fib 9) 55))
    );
}

#[test]
fn lambda_tests() {
    let mut num = 5;
    lisp!(
        (let ((mut add_num (lambda (((x i32))
                                     ())
                             (:= num (+ num x)))))
         (add_num 5))
    );
    println!("num = {}", ck!(num, 10));
}

/* rust-lang/rust#12335

#[test] #[compile_fail]
fn lambdarec_cannot_capture() {
    let mut num = 5;
    lisp!(
        (let ((mut add_num (lambda rec (((x i32))
                                        ())
                            (if (> x 0)
                             (do
                              (:= num (+ num 1))
                              (rec (- x 1)))
                             ()))))
         (add_num 5))
    );
    println!("num = {}", ck!(num, 10));
}
*/

<|endoftext|>


<commit_before>extern crate crypto;
extern crate byteorder;
extern crate rand;

use self::crypto::digest::Digest;
use self::crypto::sha2::{Sha256, Sha512};
use self::crypto::blake2b::Blake2b;
use self::crypto::mac::{Mac};
use self::crypto::aes::KeySize;
use self::crypto::aes_gcm::AesGcm;
use self::crypto::aead::{AeadEncryptor, AeadDecryptor};
use self::crypto::curve25519::{curve25519, curve25519_base};

use self::byteorder::{ByteOrder, BigEndian};
use self::rand::{OsRng, Rng};

use crypto_stuff::*;

pub struct Dh25519 {
    privkey : [u8; 32],
    pubkey  : [u8; 32]
}

pub struct CipherAESGCM {
    key : [u8; 32],
    nonce : u64
}

pub struct CipherChaChaPoly {
    key : [u8; 32],
    nonce : u64
}

pub struct HashSHA256 {
    hasher : Sha256
}

pub struct HashSHA512 {
    hasher : Sha512
}

pub struct HashBLAKE2b {
    hasher : Blake2b
}

impl Dh for Dh25519 {

    fn new(privkey: &[u8], pubkey: &[u8]) -> Dh25519 {
        let mut dh = Dh25519{privkey: [0u8; 32], pubkey: [0u8; 32]};
        copy_memory(privkey, &mut dh.privkey); /* RUSTSUCKS: Why can't I convert slice -> array? */
        copy_memory(pubkey, &mut dh.pubkey);
        dh
    }

    fn generate() -> Dh25519 {
        let mut privkey = [0u8; 32];
        let mut rng = OsRng::new().unwrap();
        rng.fill_bytes(&mut privkey);
        privkey[0] &= 248;
        privkey[31] &= 127;
        privkey[31] |= 64;
        let pubkey = curve25519_base(&privkey);
        Dh25519{privkey : privkey, pubkey : pubkey}
    }

    fn pubkey(&self) -> &[u8] {
        &self.pubkey
    }

    fn dh(&self, pubkey: &[u8]) -> [u8; DHLEN] {
        curve25519(&self.privkey, pubkey)
    }

}

impl Cipher for CipherAESGCM {

    fn new(key: &[u8], nonce: u64) -> CipherAESGCM {
        let mut cipher = CipherAESGCM{key: [0u8; 32], nonce: nonce};
        copy_memory(key, &mut cipher.key);
        cipher
    }

    fn encrypt_and_inc(&mut self, authtext: &[u8], plaintext: &[u8], out: &mut[u8]) {
        let mut nonce_bytes = [0u8; 12];
        BigEndian::write_u64(&mut nonce_bytes[4..], self.nonce);
        self.nonce += 1;
        let mut cipher = AesGcm::new(KeySize::KeySize256, &self.key, &nonce_bytes, authtext);
        let mut tag = [0u8; TAGLEN];
        cipher.encrypt(plaintext, &mut out[..plaintext.len()], &mut tag);
        copy_memory(&tag, &mut out[plaintext.len()..]);
    }

    fn decrypt_and_inc(&mut self, authtext: &[u8], ciphertext: &[u8], out: &mut[u8]) -> bool {
        let mut nonce_bytes = [0u8; 12];
        BigEndian::write_u64(&mut nonce_bytes[4..], self.nonce);
        self.nonce += 1;
        let mut cipher = AesGcm::new(KeySize::KeySize256, &self.key, &nonce_bytes, authtext);
        let text_len = ciphertext.len() - TAGLEN;
        let mut tag = [0u8; TAGLEN];
        copy_memory(&ciphertext[text_len..], &mut tag);
        cipher.decrypt(&ciphertext[..text_len], &mut out[..text_len], &tag)
    }

}

impl Hash for HashSHA256 {

    fn new() -> HashSHA256 {
        HashSHA256{hasher : Sha256::new()}
    }

    fn block_len() -> usize {
        return 64;
    }

    fn hash_len() -> usize {
        return 32;
    }

    fn input(&mut self, data: &[u8]) {
        self.hasher.input(data);
    }

    fn result(&mut self, out: &mut [u8]) {
        self.hasher.result(out);
    }
}

#[cfg(test)]
mod tests {

    extern crate rustc_serialize;

    use crypto_stuff::*;
    use super::*;
    use self::rustc_serialize::hex::{FromHex, ToHex};

    #[test]
    fn crypto_tests() {

        // SHA256 test
        {
            let mut output = [0u8; 32];
            let mut hasher = HashSHA256::new();
            hasher.input("abc".as_bytes());
            hasher.result(&mut output);
            assert!(output.to_hex() == "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
        }

        // HMAC-SHA256 test - RFC 4231
        {
            let key = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".from_hex().unwrap();
            let data = "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd".from_hex().unwrap();
            let mut output = [0u8; 32];
            HashSHA256::hmac(&key, &data, &mut output);
            assert!(output.to_hex() == "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe");
        }

        // Curve25519 test - draft-curves-10
        {
            let mut keypair = Dh25519::new(&[0; 32], &[0; 32]);
            let scalar = "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4".from_hex().unwrap();
            copy_memory(&scalar, &mut keypair.privkey);
            let public = "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c".from_hex().unwrap();
            let output = keypair.dh(&public);
            assert!(output.to_hex() == "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552");
        }

        //AES256-GCM tests - gcm-spec.pdf
        {
            // Test Case 13
            let key = [0u8; 32];
            let nonce = 0u64;
            let plaintext = [0u8; 0];
            let authtext = [0u8; 0];
            let mut ciphertext = [0u8; 16];
            let mut cipher1 = CipherAESGCM::new(&key, nonce);
            cipher1.encrypt_and_inc(&authtext, &plaintext, &mut ciphertext);
            assert!(ciphertext.to_hex() == "530f8afbc74536b9a963b4f1c4cb738b");

            let mut resulttext = [0u8; 1];
            let mut cipher2 = CipherAESGCM::new(&key, nonce);
            assert!(cipher2.decrypt_and_inc(&authtext, &ciphertext, &mut resulttext) == true);
            assert!(resulttext[0] == 0);
            ciphertext[0] ^= 1;
            assert!(cipher1.nonce == 1 && cipher2.nonce == 1);
            cipher2.nonce = 0;
            assert!(cipher2.decrypt_and_inc(&authtext, &ciphertext, &mut resulttext) == false);

            // Test Case 14
            let plaintext2 = [0u8; 16];
            let mut ciphertext2 = [0u8; 32];
            let mut cipher3 = CipherAESGCM::new(&key, 0);
            cipher3.encrypt_and_inc(&authtext, &plaintext2, &mut ciphertext2);
            assert!(ciphertext2.to_hex() == "cea7403d4d606b6e074ec5d3baf39d18d0d1c8a799996bf0265b98b5d48ab919");

            let mut resulttext2 = [1u8; 16];
            let mut cipher4 = CipherAESGCM::new(&key, 0);
            assert!(cipher4.decrypt_and_inc(&authtext, &ciphertext2, &mut resulttext2) == true);
            assert!(plaintext2 == resulttext2);
            ciphertext2[0] ^= 1;
            assert!(cipher3.nonce == 1 && cipher4.nonce == 1);
            cipher4.nonce = 0;
            assert!(cipher4.decrypt_and_inc(&authtext, &ciphertext2, &mut resulttext2) == false);
        }

    }
}
<commit_msg>Add SHA512, ChaChaPoly, BLAKE2b - untested<commit_after>extern crate crypto;
extern crate byteorder;
extern crate rand;

use self::crypto::digest::Digest;
use self::crypto::sha2::{Sha256, Sha512};
use self::crypto::blake2b::Blake2b;
use self::crypto::aes::KeySize;
use self::crypto::aes_gcm::AesGcm;
use self::crypto::chacha20poly1305::ChaCha20Poly1305;
use self::crypto::aead::{AeadEncryptor, AeadDecryptor};
use self::crypto::curve25519::{curve25519, curve25519_base};

use self::byteorder::{ByteOrder, BigEndian, LittleEndian};
use self::rand::{OsRng, Rng};

use crypto_stuff::*;

pub struct Dh25519 {
    privkey : [u8; 32],
    pubkey  : [u8; 32]
}

pub struct CipherAESGCM {
    key : [u8; 32],
    nonce : u64
}

pub struct CipherChaChaPoly {
    key : [u8; 32],
    nonce : u64
}

pub struct HashSHA256 {
    hasher : Sha256
}

pub struct HashSHA512 {
    hasher : Sha512
}

pub struct HashBLAKE2b {
    hasher : Blake2b
}

impl Dh for Dh25519 {

    fn new(privkey: &[u8], pubkey: &[u8]) -> Dh25519 {
        let mut dh = Dh25519{privkey: [0u8; 32], pubkey: [0u8; 32]};
        copy_memory(privkey, &mut dh.privkey); /* RUSTSUCKS: Why can't I convert slice -> array? */
        copy_memory(pubkey, &mut dh.pubkey);
        dh
    }

    fn generate() -> Dh25519 {
        let mut privkey = [0u8; 32];
        let mut rng = OsRng::new().unwrap();
        rng.fill_bytes(&mut privkey);
        privkey[0] &= 248;
        privkey[31] &= 127;
        privkey[31] |= 64;
        let pubkey = curve25519_base(&privkey);
        Dh25519{privkey : privkey, pubkey : pubkey}
    }

    fn pubkey(&self) -> &[u8] {
        &self.pubkey
    }

    fn dh(&self, pubkey: &[u8]) -> [u8; DHLEN] {
        curve25519(&self.privkey, pubkey)
    }

}

impl Cipher for CipherAESGCM {

    fn new(key: &[u8], nonce: u64) -> CipherAESGCM {
        let mut cipher = CipherAESGCM{key: [0u8; 32], nonce: nonce};
        copy_memory(key, &mut cipher.key);
        cipher
    }

    fn encrypt_and_inc(&mut self, authtext: &[u8], plaintext: &[u8], out: &mut[u8]) {
        let mut nonce_bytes = [0u8; 12];
        BigEndian::write_u64(&mut nonce_bytes[4..], self.nonce);
        self.nonce += 1;
        let mut cipher = AesGcm::new(KeySize::KeySize256, &self.key, &nonce_bytes, authtext);
        let mut tag = [0u8; TAGLEN];
        cipher.encrypt(plaintext, &mut out[..plaintext.len()], &mut tag);
        copy_memory(&tag, &mut out[plaintext.len()..]);
    }

    fn decrypt_and_inc(&mut self, authtext: &[u8], ciphertext: &[u8], out: &mut[u8]) -> bool {
        let mut nonce_bytes = [0u8; 12];
        BigEndian::write_u64(&mut nonce_bytes[4..], self.nonce);
        self.nonce += 1;
        let mut cipher = AesGcm::new(KeySize::KeySize256, &self.key, &nonce_bytes, authtext);
        let text_len = ciphertext.len() - TAGLEN;
        let mut tag = [0u8; TAGLEN];
        copy_memory(&ciphertext[text_len..], &mut tag);
        cipher.decrypt(&ciphertext[..text_len], &mut out[..text_len], &tag)
    }

}

impl Cipher for CipherChaChaPoly {

    fn new(key: &[u8], nonce: u64) -> CipherChaChaPoly {
        let mut cipher = CipherChaChaPoly{key: [0u8; 32], nonce: nonce};
        copy_memory(key, &mut cipher.key);
        cipher
    }

    fn encrypt_and_inc(&mut self, authtext: &[u8], plaintext: &[u8], out: &mut[u8]) {
        let mut nonce_bytes = [0u8; 8];
        LittleEndian::write_u64(&mut nonce_bytes, self.nonce);
        self.nonce += 1;
        let mut cipher = ChaCha20Poly1305::new(&self.key, &nonce_bytes, authtext);
        let mut tag = [0u8; TAGLEN];
        cipher.encrypt(plaintext, &mut out[..plaintext.len()], &mut tag);
        copy_memory(&tag, &mut out[plaintext.len()..]);
    }

    fn decrypt_and_inc(&mut self, authtext: &[u8], ciphertext: &[u8], out: &mut[u8]) -> bool {
        let mut nonce_bytes = [0u8; 8];
        LittleEndian::write_u64(&mut nonce_bytes, self.nonce);
        self.nonce += 1;
        let mut cipher = ChaCha20Poly1305::new(&self.key, &nonce_bytes, authtext);
        let text_len = ciphertext.len() - TAGLEN;
        let mut tag = [0u8; TAGLEN];
        copy_memory(&ciphertext[text_len..], &mut tag);
        cipher.decrypt(&ciphertext[..text_len], &mut out[..text_len], &tag)
    }

}

impl Hash for HashSHA256 {

    fn new() -> HashSHA256 {
        HashSHA256{hasher : Sha256::new()}
    }

    fn block_len() -> usize {
        return 64;
    }

    fn hash_len() -> usize {
        return 32;
    }

    fn input(&mut self, data: &[u8]) {
        self.hasher.input(data);
    }

    fn result(&mut self, out: &mut [u8]) {
        self.hasher.result(out);
    }
}

impl Hash for HashSHA512 {

    fn new() -> HashSHA512 {
        HashSHA512{hasher : Sha512::new()}
    }

    fn block_len() -> usize {
        return 128;
    }

    fn hash_len() -> usize {
        return 64;
    }

    fn input(&mut self, data: &[u8]) {
        self.hasher.input(data);
    }

    fn result(&mut self, out: &mut [u8]) {
        self.hasher.result(out);
    }
}

impl Hash for HashBLAKE2b {

    fn new() -> HashBLAKE2b {
        HashBLAKE2b{hasher : Blake2b::new(64)}
    }

    fn block_len() -> usize {
        return 128;
    }

    fn hash_len() -> usize {
        return 64;
    }

    fn input(&mut self, data: &[u8]) {
        self.hasher.input(data);
    }

    fn result(&mut self, out: &mut [u8]) {
        self.hasher.result(out);
    }
}

#[cfg(test)]
mod tests {

    extern crate rustc_serialize;

    use crypto_stuff::*;
    use super::*;
    use self::rustc_serialize::hex::{FromHex, ToHex};

    #[test]
    fn crypto_tests() {

        // SHA256 test
        {
            let mut output = [0u8; 32];
            let mut hasher = HashSHA256::new();
            hasher.input("abc".as_bytes());
            hasher.result(&mut output);
            assert!(output.to_hex() == "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
        }

        // HMAC-SHA256 test - RFC 4231
        {
            let key = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".from_hex().unwrap();
            let data = "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd".from_hex().unwrap();
            let mut output = [0u8; 32];
            HashSHA256::hmac(&key, &data, &mut output);
            assert!(output.to_hex() == "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe");
        }

        // Curve25519 test - draft-curves-10
        {
            let mut keypair = Dh25519::new(&[0; 32], &[0; 32]);
            let scalar = "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4".from_hex().unwrap();
            copy_memory(&scalar, &mut keypair.privkey);
            let public = "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c".from_hex().unwrap();
            let output = keypair.dh(&public);
            assert!(output.to_hex() == "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552");
        }

        //AES256-GCM tests - gcm-spec.pdf
        {
            // Test Case 13
            let key = [0u8; 32];
            let nonce = 0u64;
            let plaintext = [0u8; 0];
            let authtext = [0u8; 0];
            let mut ciphertext = [0u8; 16];
            let mut cipher1 = CipherAESGCM::new(&key, nonce);
            cipher1.encrypt_and_inc(&authtext, &plaintext, &mut ciphertext);
            assert!(ciphertext.to_hex() == "530f8afbc74536b9a963b4f1c4cb738b");

            let mut resulttext = [0u8; 1];
            let mut cipher2 = CipherAESGCM::new(&key, nonce);
            assert!(cipher2.decrypt_and_inc(&authtext, &ciphertext, &mut resulttext) == true);
            assert!(resulttext[0] == 0);
            ciphertext[0] ^= 1;
            assert!(cipher1.nonce == 1 && cipher2.nonce == 1);
            cipher2.nonce = 0;
            assert!(cipher2.decrypt_and_inc(&authtext, &ciphertext, &mut resulttext) == false);

            // Test Case 14
            let plaintext2 = [0u8; 16];
            let mut ciphertext2 = [0u8; 32];
            let mut cipher3 = CipherAESGCM::new(&key, 0);
            cipher3.encrypt_and_inc(&authtext, &plaintext2, &mut ciphertext2);
            assert!(ciphertext2.to_hex() == "cea7403d4d606b6e074ec5d3baf39d18d0d1c8a799996bf0265b98b5d48ab919");

            let mut resulttext2 = [1u8; 16];
            let mut cipher4 = CipherAESGCM::new(&key, 0);
            assert!(cipher4.decrypt_and_inc(&authtext, &ciphertext2, &mut resulttext2) == true);
            assert!(plaintext2 == resulttext2);
            ciphertext2[0] ^= 1;
            assert!(cipher3.nonce == 1 && cipher4.nonce == 1);
            cipher4.nonce = 0;
            assert!(cipher4.decrypt_and_inc(&authtext, &ciphertext2, &mut resulttext2) == false);
        }

    }
}
<|endoftext|>


<commit_before>use crate::alloc::{Allocator, Global};
use crate::raw_vec::RawVec;
use core::fmt;
use core::intrinsics::arith_offset;
use core::iter::{FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccess};
use core::marker::PhantomData;
use core::mem::{self};
use core::ptr::{self, NonNull};
use core::slice::{self};

/// An iterator that moves out of a vector.
///
/// This `struct` is created by the `into_iter` method on [`Vec`](super::Vec)
/// (provided by the [`IntoIterator`] trait).
///
/// # Example
///
/// ```
/// let v = vec![0, 1, 2];
/// let iter: std::vec::IntoIter<_> = v.into_iter();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<
    T,
    #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
> {
    pub(super) buf: NonNull<T>,
    pub(super) phantom: PhantomData<T>,
    pub(super) cap: usize,
    pub(super) alloc: A,
    pub(super) ptr: *const T,
    pub(super) end: *const T,
}

#[stable(feature = "vec_intoiter_debug", since = "1.13.0")]
impl<T: fmt::Debug, A: Allocator> fmt::Debug for IntoIter<T, A> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
    }
}

impl<T, A: Allocator> IntoIter<T, A> {
    /// Returns the remaining items of this iterator as a slice.
    ///
    /// # Examples
    ///
    /// ```
    /// let vec = vec!['a', 'b', 'c'];
    /// let mut into_iter = vec.into_iter();
    /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
    /// let _ = into_iter.next().unwrap();
    /// assert_eq!(into_iter.as_slice(), &['b', 'c']);
    /// ```
    #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")]
    pub fn as_slice(&self) -> &[T] {
        unsafe { slice::from_raw_parts(self.ptr, self.len()) }
    }

    /// Returns the remaining items of this iterator as a mutable slice.
    ///
    /// # Examples
    ///
    /// ```
    /// let vec = vec!['a', 'b', 'c'];
    /// let mut into_iter = vec.into_iter();
    /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
    /// into_iter.as_mut_slice()[2] = 'z';
    /// assert_eq!(into_iter.next().unwrap(), 'a');
    /// assert_eq!(into_iter.next().unwrap(), 'b');
    /// assert_eq!(into_iter.next().unwrap(), 'z');
    /// ```
    #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")]
    pub fn as_mut_slice(&mut self) -> &mut [T] {
        unsafe { &mut *self.as_raw_mut_slice() }
    }

    /// Returns a reference to the underlying allocator.
    #[unstable(feature = "allocator_api", issue = "32838")]
    #[inline]
    pub fn allocator(&self) -> &A {
        &self.alloc
    }

    fn as_raw_mut_slice(&mut self) -> *mut [T] {
        ptr::slice_from_raw_parts_mut(self.ptr as *mut T, self.len())
    }

    /// Drops remaining elements and relinquishes the backing allocation.
    ///
    /// This is roughly equivalent to the following, but more efficient
    ///
    /// ```
    /// # let mut into_iter = Vec::<u8>::with_capacity(10).into_iter();
    /// (&mut into_iter).for_each(core::mem::drop);
    /// unsafe { core::ptr::write(&mut into_iter, Vec::new().into_iter()); }
    /// ```
    #[cfg(not(no_global_oom_handling))]
    pub(super) fn forget_allocation_drop_remaining(&mut self) {
        let remaining = self.as_raw_mut_slice();

        // overwrite the individual fields instead of creating a new
        // struct and then overwriting &mut self.
        // this creates less assembly
        self.cap = 0;
        self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) };
        self.ptr = self.buf.as_ptr();
        self.end = self.buf.as_ptr();

        unsafe {
            ptr::drop_in_place(remaining);
        }
    }
}

#[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")]
impl<T, A: Allocator> AsRef<[T]> for IntoIter<T, A> {
    fn as_ref(&self) -> &[T] {
        self.as_slice()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<T: Send, A: Allocator + Send> Send for IntoIter<T, A> {}
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<T: Sync, A: Allocator> Sync for IntoIter<T, A> {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T, A: Allocator> Iterator for IntoIter<T, A> {
    type Item = T;

    #[inline]
    fn next(&mut self) -> Option<T> {
        if self.ptr as *const _ == self.end {
            None
        } else if mem::size_of::<T>() == 0 {
            // purposefully don't use 'ptr.offset' because for
            // vectors with 0-size elements this would return the
            // same pointer.
            self.ptr = unsafe { arith_offset(self.ptr as *const i8, 1) as *mut T };

            // Make up a value of this ZST.
            Some(unsafe { mem::zeroed() })
        } else {
            let old = self.ptr;
            self.ptr = unsafe { self.ptr.offset(1) };

            Some(unsafe { ptr::read(old) })
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let exact = if mem::size_of::<T>() == 0 {
            (self.end as usize).wrapping_sub(self.ptr as usize)
        } else {
            unsafe { self.end.offset_from(self.ptr) as usize }
        };
        (exact, Some(exact))
    }

    #[inline]
    fn count(self) -> usize {
        self.len()
    }

    #[doc(hidden)]
    unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> Self::Item
    where
        Self: TrustedRandomAccess,
    {
        // SAFETY: the caller must guarantee that `i` is in bounds of the
        // `Vec<T>`, so `i` cannot overflow an `isize`, and the `self.ptr.add(i)`
        // is guaranteed to pointer to an element of the `Vec<T>` and
        // thus guaranteed to be valid to dereference.
        //
        // Also note the implementation of `Self: TrustedRandomAccess` requires
        // that `T: Copy` so reading elements from the buffer doesn't invalidate
        // them for `Drop`.
        unsafe {
            if mem::size_of::<T>() == 0 { mem::zeroed() } else { ptr::read(self.ptr.add(i)) }
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
    #[inline]
    fn next_back(&mut self) -> Option<T> {
        if self.end == self.ptr {
            None
        } else if mem::size_of::<T>() == 0 {
            // See above for why 'ptr.offset' isn't used
            self.end = unsafe { arith_offset(self.end as *const i8, -1) as *mut T };

            // Make up a value of this ZST.
            Some(unsafe { mem::zeroed() })
        } else {
            self.end = unsafe { self.end.offset(-1) };

            Some(unsafe { ptr::read(self.end) })
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T, A: Allocator> ExactSizeIterator for IntoIter<T, A> {
    fn is_empty(&self) -> bool {
        self.ptr == self.end
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<T, A: Allocator> FusedIterator for IntoIter<T, A> {}

#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<T, A: Allocator> TrustedLen for IntoIter<T, A> {}

#[doc(hidden)]
#[unstable(issue = "none", feature = "std_internals")]
// T: Copy as approximation for !Drop since get_unchecked does not advance self.ptr
// and thus we can't implement drop-handling
unsafe impl<T, A: Allocator> TrustedRandomAccess for IntoIter<T, A>
where
    T: Copy,
{
    const MAY_HAVE_SIDE_EFFECT: bool = false;
}

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "vec_into_iter_clone", since = "1.8.0")]
impl<T: Clone, A: Allocator + Clone> Clone for IntoIter<T, A> {
    #[cfg(not(test))]
    fn clone(&self) -> Self {
        self.as_slice().to_vec_in(self.alloc.clone()).into_iter()
    }
    #[cfg(test)]
    fn clone(&self) -> Self {
        crate::slice::to_vec(self.as_slice(), self.alloc.clone()).into_iter()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter<T, A> {
    fn drop(&mut self) {
        struct DropGuard<'a, T, A: Allocator>(&'a mut IntoIter<T, A>);

        impl<T, A: Allocator> Drop for DropGuard<'_, T, A> {
            fn drop(&mut self) {
                unsafe {
                    // `IntoIter::alloc` is not used anymore after this
                    let alloc = ptr::read(&self.0.alloc);
                    // RawVec handles deallocation
                    let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc);
                }
            }
        }

        let guard = DropGuard(self);
        // destroy the remaining elements
        unsafe {
            ptr::drop_in_place(guard.0.as_raw_mut_slice());
        }
        // now `guard` will be dropped and do the rest
    }
}

#[unstable(issue = "none", feature = "inplace_iteration")]
#[doc(hidden)]
unsafe impl<T, A: Allocator> InPlaceIterable for IntoIter<T, A> {}

#[unstable(issue = "none", feature = "inplace_iteration")]
#[doc(hidden)]
unsafe impl<T, A: Allocator> SourceIter for IntoIter<T, A> {
    type Source = Self;

    #[inline]
    unsafe fn as_inner(&mut self) -> &mut Self::Source {
        self
    }
}

// internal helper trait for in-place iteration specialization.
#[rustc_specialization_trait]
pub(crate) trait AsIntoIter {
    type Item;
    fn as_into_iter(&mut self) -> &mut IntoIter<Self::Item>;
}

impl<T> AsIntoIter for IntoIter<T> {
    type Item = T;

    fn as_into_iter(&mut self) -> &mut IntoIter<Self::Item> {
        self
    }
}
<commit_msg>Remove unsound TrustedRandomAccess implementations<commit_after>use crate::alloc::{Allocator, Global};
use crate::raw_vec::RawVec;
use core::fmt;
use core::intrinsics::arith_offset;
use core::iter::{FusedIterator, InPlaceIterable, SourceIter, TrustedLen};
use core::marker::PhantomData;
use core::mem::{self};
use core::ptr::{self, NonNull};
use core::slice::{self};

/// An iterator that moves out of a vector.
///
/// This `struct` is created by the `into_iter` method on [`Vec`](super::Vec)
/// (provided by the [`IntoIterator`] trait).
///
/// # Example
///
/// ```
/// let v = vec![0, 1, 2];
/// let iter: std::vec::IntoIter<_> = v.into_iter();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<
    T,
    #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
> {
    pub(super) buf: NonNull<T>,
    pub(super) phantom: PhantomData<T>,
    pub(super) cap: usize,
    pub(super) alloc: A,
    pub(super) ptr: *const T,
    pub(super) end: *const T,
}

#[stable(feature = "vec_intoiter_debug", since = "1.13.0")]
impl<T: fmt::Debug, A: Allocator> fmt::Debug for IntoIter<T, A> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
    }
}

impl<T, A: Allocator> IntoIter<T, A> {
    /// Returns the remaining items of this iterator as a slice.
    ///
    /// # Examples
    ///
    /// ```
    /// let vec = vec!['a', 'b', 'c'];
    /// let mut into_iter = vec.into_iter();
    /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
    /// let _ = into_iter.next().unwrap();
    /// assert_eq!(into_iter.as_slice(), &['b', 'c']);
    /// ```
    #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")]
    pub fn as_slice(&self) -> &[T] {
        unsafe { slice::from_raw_parts(self.ptr, self.len()) }
    }

    /// Returns the remaining items of this iterator as a mutable slice.
    ///
    /// # Examples
    ///
    /// ```
    /// let vec = vec!['a', 'b', 'c'];
    /// let mut into_iter = vec.into_iter();
    /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
    /// into_iter.as_mut_slice()[2] = 'z';
    /// assert_eq!(into_iter.next().unwrap(), 'a');
    /// assert_eq!(into_iter.next().unwrap(), 'b');
    /// assert_eq!(into_iter.next().unwrap(), 'z');
    /// ```
    #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")]
    pub fn as_mut_slice(&mut self) -> &mut [T] {
        unsafe { &mut *self.as_raw_mut_slice() }
    }

    /// Returns a reference to the underlying allocator.
    #[unstable(feature = "allocator_api", issue = "32838")]
    #[inline]
    pub fn allocator(&self) -> &A {
        &self.alloc
    }

    fn as_raw_mut_slice(&mut self) -> *mut [T] {
        ptr::slice_from_raw_parts_mut(self.ptr as *mut T, self.len())
    }

    /// Drops remaining elements and relinquishes the backing allocation.
    ///
    /// This is roughly equivalent to the following, but more efficient
    ///
    /// ```
    /// # let mut into_iter = Vec::<u8>::with_capacity(10).into_iter();
    /// (&mut into_iter).for_each(core::mem::drop);
    /// unsafe { core::ptr::write(&mut into_iter, Vec::new().into_iter()); }
    /// ```
    #[cfg(not(no_global_oom_handling))]
    pub(super) fn forget_allocation_drop_remaining(&mut self) {
        let remaining = self.as_raw_mut_slice();

        // overwrite the individual fields instead of creating a new
        // struct and then overwriting &mut self.
        // this creates less assembly
        self.cap = 0;
        self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) };
        self.ptr = self.buf.as_ptr();
        self.end = self.buf.as_ptr();

        unsafe {
            ptr::drop_in_place(remaining);
        }
    }
}

#[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")]
impl<T, A: Allocator> AsRef<[T]> for IntoIter<T, A> {
    fn as_ref(&self) -> &[T] {
        self.as_slice()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<T: Send, A: Allocator + Send> Send for IntoIter<T, A> {}
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<T: Sync, A: Allocator> Sync for IntoIter<T, A> {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T, A: Allocator> Iterator for IntoIter<T, A> {
    type Item = T;

    #[inline]
    fn next(&mut self) -> Option<T> {
        if self.ptr as *const _ == self.end {
            None
        } else if mem::size_of::<T>() == 0 {
            // purposefully don't use 'ptr.offset' because for
            // vectors with 0-size elements this would return the
            // same pointer.
            self.ptr = unsafe { arith_offset(self.ptr as *const i8, 1) as *mut T };

            // Make up a value of this ZST.
            Some(unsafe { mem::zeroed() })
        } else {
            let old = self.ptr;
            self.ptr = unsafe { self.ptr.offset(1) };

            Some(unsafe { ptr::read(old) })
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let exact = if mem::size_of::<T>() == 0 {
            (self.end as usize).wrapping_sub(self.ptr as usize)
        } else {
            unsafe { self.end.offset_from(self.ptr) as usize }
        };
        (exact, Some(exact))
    }

    #[inline]
    fn count(self) -> usize {
        self.len()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
    #[inline]
    fn next_back(&mut self) -> Option<T> {
        if self.end == self.ptr {
            None
        } else if mem::size_of::<T>() == 0 {
            // See above for why 'ptr.offset' isn't used
            self.end = unsafe { arith_offset(self.end as *const i8, -1) as *mut T };

            // Make up a value of this ZST.
            Some(unsafe { mem::zeroed() })
        } else {
            self.end = unsafe { self.end.offset(-1) };

            Some(unsafe { ptr::read(self.end) })
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T, A: Allocator> ExactSizeIterator for IntoIter<T, A> {
    fn is_empty(&self) -> bool {
        self.ptr == self.end
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<T, A: Allocator> FusedIterator for IntoIter<T, A> {}

#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<T, A: Allocator> TrustedLen for IntoIter<T, A> {}

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "vec_into_iter_clone", since = "1.8.0")]
impl<T: Clone, A: Allocator + Clone> Clone for IntoIter<T, A> {
    #[cfg(not(test))]
    fn clone(&self) -> Self {
        self.as_slice().to_vec_in(self.alloc.clone()).into_iter()
    }
    #[cfg(test)]
    fn clone(&self) -> Self {
        crate::slice::to_vec(self.as_slice(), self.alloc.clone()).into_iter()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter<T, A> {
    fn drop(&mut self) {
        struct DropGuard<'a, T, A: Allocator>(&'a mut IntoIter<T, A>);

        impl<T, A: Allocator> Drop for DropGuard<'_, T, A> {
            fn drop(&mut self) {
                unsafe {
                    // `IntoIter::alloc` is not used anymore after this
                    let alloc = ptr::read(&self.0.alloc);
                    // RawVec handles deallocation
                    let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc);
                }
            }
        }

        let guard = DropGuard(self);
        // destroy the remaining elements
        unsafe {
            ptr::drop_in_place(guard.0.as_raw_mut_slice());
        }
        // now `guard` will be dropped and do the rest
    }
}

#[unstable(issue = "none", feature = "inplace_iteration")]
#[doc(hidden)]
unsafe impl<T, A: Allocator> InPlaceIterable for IntoIter<T, A> {}

#[unstable(issue = "none", feature = "inplace_iteration")]
#[doc(hidden)]
unsafe impl<T, A: Allocator> SourceIter for IntoIter<T, A> {
    type Source = Self;

    #[inline]
    unsafe fn as_inner(&mut self) -> &mut Self::Source {
        self
    }
}

// internal helper trait for in-place iteration specialization.
#[rustc_specialization_trait]
pub(crate) trait AsIntoIter {
    type Item;
    fn as_into_iter(&mut self) -> &mut IntoIter<Self::Item>;
}

impl<T> AsIntoIter for IntoIter<T> {
    type Item = T;

    fn as_into_iter(&mut self) -> &mut IntoIter<Self::Item> {
        self
    }
}
<|endoftext|>


<commit_before><commit_msg>Auto merge of #208 - EnricoMiccoli:patch-1, r=komaeda<commit_after><|endoftext|>


<commit_before><commit_msg>lucet-runtime-tests: add stack overflow test suite<commit_after><|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Call_a_foreign-language_function

extern crate libc;

use libc::c_char;
use std::ffi::CString;

extern "C" {
    // C functions are declared in an `extern "C"` block.
    fn strcmp(a: *const c_char, b: *const c_char) -> isize;
}

#[cfg(not(test))]
fn main() {
    let a = CString::from_slice(b"a");
    let b = CString::from_slice(b"b");

    println!("{}", unsafe {
        strcmp(a.as_ptr(), b.as_ptr())
    });
}

#[cfg(test)]
#[test]
fn test_strcmp() {
    let a = CString::from_slice(b"a");
    let b = CString::from_slice(b"b");

    assert_eq!(unsafe {
        strcmp(a.as_ptr(), b.as_ptr())
    }, -1);
}
<commit_msg>Fixed call_foreign_function test<commit_after>// Implements http://rosettacode.org/wiki/Call_a_foreign-language_function

extern crate libc;

use libc::c_char;
use std::ffi::CString;

extern "C" {
    // C functions are declared in an `extern "C"` block.
    fn strcmp(a: *const c_char, b: *const c_char) -> i32;
}

#[cfg(not(test))]
fn main() {
    let a = CString::from_slice(b"a");
    let b = CString::from_slice(b"b");

    println!("{}", unsafe {
        strcmp(a.as_ptr(), b.as_ptr())
    });
}

#[cfg(test)]
#[test]
fn test_strcmp() {
    let a = CString::from_slice(b"a");
    let b = CString::from_slice(b"b");

    assert_eq!(unsafe {
        strcmp(a.as_ptr(), b.as_ptr())
    }, -1);
}
<|endoftext|>


<commit_before>extern crate futures;
extern crate tokio_io;

use futures::future::ok;
use std::cell::RefCell;
use std::rc::Rc;

use super::{BoxedNewPeerFuture, Peer};

use std::io::{Error as IoError, Read, Write};
use tokio_io::{AsyncRead, AsyncWrite};

use super::{once, Handle, Options, PeerConstructor, ProgramState, Specifier};
use futures::Future;
use std::ops::DerefMut;

#[derive(Debug)]
pub struct Reuser(pub Rc<Specifier>);
impl Specifier for Reuser {
    fn construct(&self, h: &Handle, ps: &mut ProgramState, opts: Rc<Options>) -> PeerConstructor {
        let mut reuser = ps.reuser.clone();
        let inner = || self.0.construct(h, ps, opts).get_only_first_conn();
        once(connection_reuser(&mut reuser, inner))
    }
    specifier_boilerplate!(singleconnect has_subspec typ=Reuser globalstate);
    self_0_is_subspecifier!(...);
}

specifier_class!(
    name=ReuserClass,
    target=Reuser,
    prefixes=["reuse:"],
    arg_handling=subspec,
    help="TODO"
);

type PeerSlot = Rc<RefCell<Option<Peer>>>;

#[derive(Default, Clone)]
pub struct GlobalState(PeerSlot);

#[derive(Clone)]
struct PeerHandle(PeerSlot);

impl Read for PeerHandle {
    fn read(&mut self, b: &mut [u8]) -> Result<usize, IoError> {
        if let &mut Some(ref mut x) = self.0.borrow_mut().deref_mut() {
            x.0.read(b)
        } else {
            unreachable!()
        }
    }
}
impl AsyncRead for PeerHandle {}

impl Write for PeerHandle {
    fn write(&mut self, b: &[u8]) -> Result<usize, IoError> {
        if let &mut Some(ref mut x) = self.0.borrow_mut().deref_mut() {
            x.1.write(b)
        } else {
            unreachable!()
        }
    }
    fn flush(&mut self) -> Result<(), IoError> {
        if let &mut Some(ref mut x) = self.0.borrow_mut().deref_mut() {
            x.1.flush()
        } else {
            unreachable!()
        }
    }
}
impl AsyncWrite for PeerHandle {
    fn shutdown(&mut self) -> futures::Poll<(), IoError> {
        if let &mut Some(ref mut x) = self.0.borrow_mut().deref_mut() {
            x.1.shutdown()
        } else {
            unreachable!()
        }
    }
}

pub fn connection_reuser<F: FnOnce() -> BoxedNewPeerFuture>(
    s: &mut GlobalState,
    inner_peer: F,
) -> BoxedNewPeerFuture {
    let need_init = s.0.borrow().is_none();

    let rc = s.0.clone();

    if need_init {
        info!("Initializing");
        Box::new(inner_peer().and_then(move |inner| {
            {
                let mut b = rc.borrow_mut();
                let x: &mut Option<Peer> = b.deref_mut();
                *x = Some(inner);
            }

            let ps: PeerSlot = rc.clone();

            let ph1 = PeerHandle(ps);
            let ph2 = ph1.clone();
            let peer = Peer::new(ph1, ph2);
            ok(peer)
        })) as BoxedNewPeerFuture
    } else {
        info!("Reusing");
        let ps: PeerSlot = rc.clone();

        let ph1 = PeerHandle(ps);
        let ph2 = ph1.clone();
        let peer = Peer::new(ph1, ph2);
        Box::new(ok(peer)) as BoxedNewPeerFuture
    }
}
<commit_msg>reuse: - don't shutdown connection to be reused<commit_after>extern crate futures;
extern crate tokio_io;

use futures::future::ok;
use std::cell::RefCell;
use std::rc::Rc;

use super::{BoxedNewPeerFuture, Peer};

use std::io::{Error as IoError, Read, Write};
use tokio_io::{AsyncRead, AsyncWrite};

use super::{once, Handle, Options, PeerConstructor, ProgramState, Specifier};
use futures::Future;
use std::ops::DerefMut;

#[derive(Debug)]
pub struct Reuser(pub Rc<Specifier>);
impl Specifier for Reuser {
    fn construct(&self, h: &Handle, ps: &mut ProgramState, opts: Rc<Options>) -> PeerConstructor {
        let mut reuser = ps.reuser.clone();
        let inner = || self.0.construct(h, ps, opts).get_only_first_conn();
        once(connection_reuser(&mut reuser, inner))
    }
    specifier_boilerplate!(singleconnect has_subspec typ=Reuser globalstate);
    self_0_is_subspecifier!(...);
}

specifier_class!(
    name=ReuserClass,
    target=Reuser,
    prefixes=["reuse:"],
    arg_handling=subspec,
    help="TODO"
);

type PeerSlot = Rc<RefCell<Option<Peer>>>;

#[derive(Default, Clone)]
pub struct GlobalState(PeerSlot);

#[derive(Clone)]
struct PeerHandle(PeerSlot);

impl Read for PeerHandle {
    fn read(&mut self, b: &mut [u8]) -> Result<usize, IoError> {
        if let &mut Some(ref mut x) = self.0.borrow_mut().deref_mut() {
            x.0.read(b)
        } else {
            unreachable!()
        }
    }
}
impl AsyncRead for PeerHandle {}

impl Write for PeerHandle {
    fn write(&mut self, b: &[u8]) -> Result<usize, IoError> {
        if let &mut Some(ref mut x) = self.0.borrow_mut().deref_mut() {
            x.1.write(b)
        } else {
            unreachable!()
        }
    }
    fn flush(&mut self) -> Result<(), IoError> {
        if let &mut Some(ref mut x) = self.0.borrow_mut().deref_mut() {
            x.1.flush()
        } else {
            unreachable!()
        }
    }
}
impl AsyncWrite for PeerHandle {
    fn shutdown(&mut self) -> futures::Poll<(), IoError> {
        if let &mut Some(ref mut _x) = self.0.borrow_mut().deref_mut() {
            // Ignore shutdown attempts
            Ok(futures::Async::Ready(()))
            //_x.1.shutdown()
        } else {
            unreachable!()
        }
    }
}

pub fn connection_reuser<F: FnOnce() -> BoxedNewPeerFuture>(
    s: &mut GlobalState,
    inner_peer: F,
) -> BoxedNewPeerFuture {
    let need_init = s.0.borrow().is_none();

    let rc = s.0.clone();

    if need_init {
        info!("Initializing");
        Box::new(inner_peer().and_then(move |inner| {
            {
                let mut b = rc.borrow_mut();
                let x: &mut Option<Peer> = b.deref_mut();
                *x = Some(inner);
            }

            let ps: PeerSlot = rc.clone();

            let ph1 = PeerHandle(ps);
            let ph2 = ph1.clone();
            let peer = Peer::new(ph1, ph2);
            ok(peer)
        })) as BoxedNewPeerFuture
    } else {
        info!("Reusing");
        let ps: PeerSlot = rc.clone();

        let ph1 = PeerHandle(ps);
        let ph2 = ph1.clone();
        let peer = Peer::new(ph1, ph2);
        Box::new(ok(peer)) as BoxedNewPeerFuture
    }
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use collections::hashmap::HashMap;
use serialize::{Decodable, json};
use glfw;
use cgmath::vector::{Vec3, Vec2};
use core::map::MapPosIter;
use core::types::{Size2, MInt, MBool, UnitId, PlayerId, MapPos};
use core::game_state::GameState;
use core::pathfinder::Pathfinder;
use core::misc::read_file;
use core::core::{
    Core,
    Unit,
    CommandEndTurn,
    CommandMove,
    CommandCreateUnit,
    CommandAttackUnit,
    Event,
    EventMove,
    EventEndTurn,
    EventCreateUnit,
    EventAttackUnit,
};
use visualizer::gl_helpers::{
    uniform_mat4f,
    set_clear_color,
    clear_screen,
    init_opengl,
    load_gl_funcs_with,
    set_viewport,
    tr,
};
use visualizer::camera::Camera;
use visualizer::geom::Geom;
use visualizer::tile_picker::TilePicker;
use visualizer::obj;
use visualizer::mesh::Mesh;
use visualizer::types::{
    Scene,
    VertexCoord,
    TextureCoord,
    MFloat,
    Point2,
    MatId,
};
use visualizer::event_visualizer::{
    EventVisualizer,
    EventMoveVisualizer,
    EventEndTurnVisualizer,
    EventCreateUnitVisualizer,
    EventAttackUnitVisualizer,
};
use visualizer::shader::Shader;
use visualizer::texture::Texture;

fn build_hex_mesh(&geom: &Geom, map_size: Size2<MInt>) -> ~[VertexCoord] {
    let mut vertex_data = ~[];
    for tile_pos in MapPosIter::new(map_size) {
        let pos = geom.map_pos_to_world_pos(tile_pos);
        for num in range(0 as MInt, 6) {
            let vertex = geom.index_to_hex_vertex(num);
            let next_vertex = geom.index_to_hex_vertex(num + 1);
            vertex_data.push(pos + vertex);
            vertex_data.push(pos + next_vertex);
            vertex_data.push(pos + Vec3::zero());
        }
    }
    vertex_data
}

fn build_hex_tex_coord(map_size: Size2<MInt>) -> ~[TextureCoord] {
    let mut vertex_data = ~[];
    for _ in MapPosIter::new(map_size) {
        for _ in range(0, 6) {
            vertex_data.push(Vec2{x: 0.0, y: 0.0});
            vertex_data.push(Vec2{x: 1.0, y: 0.0});
            vertex_data.push(Vec2{x: 0.5, y: 0.5});
        }
    }
    vertex_data
}

fn read_win_size(config_path: &str) -> Size2<MInt> {
    let path = Path::new(config_path);
    let json = json::from_str(read_file(&path)).unwrap();
    let mut decoder = json::Decoder::new(json);
    let size: Size2<MInt> = Decodable::decode(&mut decoder);
    size
}

fn init_win(win_size: Size2<MInt>) -> glfw::Window {
    glfw::set_error_callback(~glfw::LogErrorHandler);
    let init_status = glfw::init();
    if !init_status.is_ok() {
        fail!("Failed to initialize GLFW");
    }
    let win = glfw::Window::create(
        win_size.w as u32,
        win_size.h as u32,
        "Marauder",
        glfw::Windowed,
    ).unwrap();
    win.make_context_current();
    win.set_all_polling(true);
    win
}

fn get_scenes(players_count: MInt) -> HashMap<PlayerId, Scene> {
    let mut m = HashMap::new();
    for i in range(0, players_count) {
        m.insert(PlayerId(i), HashMap::new());
    }
    m
}

fn get_game_states(players_count: MInt) -> HashMap<PlayerId, GameState> {
    let mut m = HashMap::new();
    for i in range(0, players_count) {
        m.insert(PlayerId(i), GameState::new());
    }
    m
}

fn get_pathfinders(
    players_count: MInt,
    map_size: Size2<MInt>,
) -> HashMap<PlayerId, Pathfinder> {
    let mut m = HashMap::new();
    for i in range(0, players_count) {
        m.insert(PlayerId(i), Pathfinder::new(map_size));
    }
    m
}

fn get_map_mesh(geom: &Geom, map_size: Size2<MInt>, shader: &Shader) -> Mesh {
    let tex = Texture::new(~"data/floor.png");
    let mut mesh = Mesh::new(build_hex_mesh(geom, map_size));
    mesh.set_texture(tex, build_hex_tex_coord(map_size));
    mesh.prepare(shader);
    mesh
}

fn load_unit_mesh(shader: &Shader) -> Mesh {
    let tex = Texture::new(~"data/tank.png");
    let obj = obj::Model::new("data/tank.obj");
    let mut mesh = Mesh::new(obj.build());
    mesh.set_texture(tex, obj.build_tex_coord());
    mesh.prepare(shader);
    mesh
}

pub struct Visualizer<'a> {
    shader: Shader,
    map_mesh: Mesh,
    unit_mesh: Mesh,
    mvp_mat_id: MatId,
    win: glfw::Window,
    mouse_pos: Point2<MFloat>,
    camera: Camera,
    tile_picker: ~TilePicker,
    selected_tile_pos: Option<MapPos>,
    selected_unit_id: Option<UnitId>,
    geom: Geom,
    scenes: HashMap<PlayerId, Scene>,
    core: ~Core<'a>,
    event: Option<Event>,
    event_visualizer: Option<~EventVisualizer>,
    game_state: HashMap<PlayerId, GameState>,
    pathfinders: HashMap<PlayerId, Pathfinder>,
}

impl<'a> Visualizer<'a> {
    pub fn new() -> ~Visualizer {
        let players_count = 2;
        let win_size = read_win_size("config.json");
        let win = init_win(win_size);
        load_gl_funcs_with(glfw::get_proc_address);
        init_opengl();
        let geom = Geom::new();
        let core = Core::new();
        let map_size = core.map_size();
        let tile_picker = TilePicker::new(
            win_size, &geom, core.map_size());
        let shader = Shader::new("normal.vs.glsl", "normal.fs.glsl");
        let mvp_mat_id = MatId(shader.get_uniform("mvp_mat"));
        let vis = ~Visualizer {
            map_mesh: get_map_mesh(&geom, map_size, &shader),
            unit_mesh: load_unit_mesh(&shader),
            mvp_mat_id: mvp_mat_id,
            shader: shader,
            win: win,
            mouse_pos: Vec2::zero(),
            camera: Camera::new(),
            tile_picker: tile_picker,
            selected_tile_pos: None,
            selected_unit_id: None,
            geom: geom,
            core: core,
            event_visualizer: None,
            event: None,
            scenes: get_scenes(players_count),
            game_state: get_game_states(players_count),
            pathfinders: get_pathfinders(players_count, map_size),
        };
        vis
    }

    fn win<'a>(&'a self) -> &'a glfw::Window {
        &self.win
    }

    fn scene<'a>(&'a self) -> &'a Scene {
        self.scenes.get(&self.core.player_id())
    }

    fn unit_at_opt(&'a self, pos: MapPos) -> Option<&'a Unit> {
        let mut res = None;
        let id = self.core.player_id();
        for (_, unit) in self.game_state.get(&id).units.iter() {
            if unit.pos == pos {
                res = Some(unit);
                break;
            }
        }
        res
    }

    fn draw_units(&self) {
        for (_, unit) in self.scene().iter() {
            let m = tr(self.camera.mat(), unit.pos);
            uniform_mat4f(self.mvp_mat_id, &m);
            self.unit_mesh.draw(&self.shader);
        }
    }

    fn draw_map(&self) {
        uniform_mat4f(self.mvp_mat_id, &self.camera.mat());
        self.map_mesh.draw(&self.shader);
    }

    fn draw(&mut self) {
        set_clear_color(0.3, 0.3, 0.3);
        clear_screen();
        self.shader.activate();
        self.draw_units();
        self.draw_map();
        if !self.event_visualizer.is_none() {
            let scene = self.scenes.get_mut(&self.core.player_id());
            self.event_visualizer.get_mut_ref().draw(&self.geom, scene);
        }
        self.win().swap_buffers();
    }

    pub fn is_running(&self) -> MBool {
        return !self.win().should_close()
    }

    fn end_turn(&mut self) {
        self.core.do_command(CommandEndTurn);
        self.selected_unit_id = None;
    }

    fn create_unit(&mut self) {
        let pos_opt = self.selected_tile_pos;
        if pos_opt.is_some() {
            let pos = pos_opt.unwrap();
            if self.unit_at_opt(pos).is_none() {
                let cmd = CommandCreateUnit(pos);
                self.core.do_command(cmd);
            }
        }
    }

    fn attack_unit(&mut self) {
        let pos_opt = self.selected_tile_pos;
        if pos_opt.is_some() {
            let pos = pos_opt.unwrap();
            if self.unit_at_opt(pos).is_some() {
                let defender_id = self.unit_at_opt(pos).unwrap().id;
                let cmd = CommandAttackUnit(UnitId(0), defender_id);
                self.core.do_command(cmd);
            }
        }
    }

    fn handle_key_event(&mut self, key: glfw::Key) {
        match key {
            glfw::KeyEscape | glfw::KeyQ => {
                self.win().set_should_close(true);
            },
            glfw::KeyUp => self.camera.move(270.0),
            glfw::KeyDown => self.camera.move(90.0),
            glfw::KeyRight => self.camera.move(0.0),
            glfw::KeyLeft => self.camera.move(180.0),
            glfw::KeyMinus => self.camera.zoom += 1.0,
            glfw::KeyEqual => self.camera.zoom -= 1.0,
            _ => {},
        }
        if self.event_visualizer.is_some() {
            return;
        }
        match key {
            glfw::KeyT => self.end_turn(),
            glfw::KeyU => self.create_unit(),
            glfw::KeyA => self.attack_unit(),
            _ => {},
        }
    }

    fn handle_cursor_pos_event(&mut self, pos: Point2<MFloat>) {
        let button = self.win().get_mouse_button(glfw::MouseButtonRight);
        if button == glfw::Press {
            self.camera.z_angle += (self.mouse_pos.x - pos.x) / 2.0;
            self.camera.x_angle += (self.mouse_pos.y - pos.y) / 2.0;
        }
        self.mouse_pos = pos;
    }

    fn handle_mouse_button_event(&mut self) {
        if self.event_visualizer.is_some() {
            return;
        }
        if self.selected_tile_pos.is_some() {
            let pos = self.selected_tile_pos.unwrap();
            if self.unit_at_opt(pos).is_some() {
                let unit_id = self.unit_at_opt(pos).unwrap().id;
                let state = self.game_state.get_mut(&self.core.player_id());
                self.selected_unit_id = Some(unit_id);
                let pf = self.pathfinders.get_mut(&self.core.player_id());
                pf.fill_map(state, state.units.get(&unit_id));
            } else if self.selected_unit_id.is_some() {
                let unit_id = self.selected_unit_id.unwrap();
                let pf = self.pathfinders.get_mut(&self.core.player_id());
                let path = pf.get_path(pos);
                self.core.do_command(CommandMove(unit_id, path));
            }
        }
    }

    fn get_events(&mut self) -> ~[glfw::WindowEvent] {
        glfw::poll_events();
        let mut events = ~[];
        for (_, event) in self.win().flush_events() {
            events.push(event);
        }
        events
    }

    fn handle_event(&mut self, event: glfw::WindowEvent) {
        match event {
            glfw::KeyEvent(key, _, glfw::Press, _) => {
                self.handle_key_event(key);
            },
            glfw::CursorPosEvent(x, y) => {
                let p = Vec2{x: x as MFloat, y: y as MFloat};
                self.handle_cursor_pos_event(p);
            },
            glfw::MouseButtonEvent(glfw::MouseButtonLeft, glfw::Press, _) => {
                self.handle_mouse_button_event();
            },
            glfw::SizeEvent(w, h) => {
                set_viewport(Size2{w: w, h: h});
                self.tile_picker.set_win_size(Size2{w: w, h: h});
            },
            _ => {},
        }
    }

    fn handle_events(&mut self) {
        for event in self.get_events().iter() {
            self.handle_event(*event);
        }
    }

    fn pick_tile(&mut self) {
        let mouse_pos = Vec2 {
            x: self.mouse_pos.x as MInt,
            y: self.mouse_pos.y as MInt,
        };
        self.selected_tile_pos =
            self.tile_picker.pick_tile(&self.camera, mouse_pos);
    }

    fn make_event_visualizer(&mut self, event: &Event) -> ~EventVisualizer {
        match *event {
            EventMove(ref unit_id, ref path) => {
                EventMoveVisualizer::new(*unit_id, path.clone())
            },
            EventEndTurn(_, _) => {
                EventEndTurnVisualizer::new()
            },
            EventCreateUnit(id, ref pos) => {
                EventCreateUnitVisualizer::new(id, *pos)
            },
            EventAttackUnit(attacker_id, defender_id) => {
                EventAttackUnitVisualizer::new(attacker_id, defender_id)
            },
        }
    }

    fn logic(&mut self) {
        if self.event_visualizer.is_none() {
            let event_opt = self.core.get_event();
            if event_opt.is_some() {
                let event = event_opt.unwrap();
                let vis = self.make_event_visualizer(&event);
                self.event = Some(event);
                self.event_visualizer = Some(vis);
                let scene = self.scenes.get_mut(&self.core.player_id());
                self.event_visualizer.get_mut_ref().start(&self.geom, scene);
            }
        } else if self.event_visualizer.get_ref().is_finished() {
            let scene = self.scenes.get_mut(&self.core.player_id());
            self.event_visualizer.get_mut_ref().end(&self.geom, scene);
            let state = self.game_state.get_mut(&self.core.player_id());
            state.apply_event(self.event.get_ref());
            self.event_visualizer = None;
            self.event = None;
            if self.selected_unit_id.is_some() {
                let unit_id = self.selected_unit_id.unwrap();
                let pf = self.pathfinders.get_mut(&self.core.player_id());
                pf.fill_map(state, state.units.get(&unit_id));
            }
        }
    }

    pub fn tick(&mut self) {
        self.handle_events();
        self.logic();
        self.pick_tile();
        self.draw();
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>visualizer.rs: Style fix: 'use core::core;'<commit_after>// See LICENSE file for copyright and license details.

use collections::hashmap::HashMap;
use serialize::{Decodable, json};
use glfw;
use cgmath::vector::{Vec3, Vec2};
use core::map::MapPosIter;
use core::types::{Size2, MInt, MBool, UnitId, PlayerId, MapPos};
use core::game_state::GameState;
use core::pathfinder::Pathfinder;
use core::misc::read_file;
use core::core;
use visualizer::gl_helpers::{
    uniform_mat4f,
    set_clear_color,
    clear_screen,
    init_opengl,
    load_gl_funcs_with,
    set_viewport,
    tr,
};
use visualizer::camera::Camera;
use visualizer::geom::Geom;
use visualizer::tile_picker::TilePicker;
use visualizer::obj;
use visualizer::mesh::Mesh;
use visualizer::types::{
    Scene,
    VertexCoord,
    TextureCoord,
    MFloat,
    Point2,
    MatId,
};
use visualizer::event_visualizer::{
    EventVisualizer,
    EventMoveVisualizer,
    EventEndTurnVisualizer,
    EventCreateUnitVisualizer,
    EventAttackUnitVisualizer,
};
use visualizer::shader::Shader;
use visualizer::texture::Texture;

fn build_hex_mesh(&geom: &Geom, map_size: Size2<MInt>) -> ~[VertexCoord] {
    let mut vertex_data = ~[];
    for tile_pos in MapPosIter::new(map_size) {
        let pos = geom.map_pos_to_world_pos(tile_pos);
        for num in range(0 as MInt, 6) {
            let vertex = geom.index_to_hex_vertex(num);
            let next_vertex = geom.index_to_hex_vertex(num + 1);
            vertex_data.push(pos + vertex);
            vertex_data.push(pos + next_vertex);
            vertex_data.push(pos + Vec3::zero());
        }
    }
    vertex_data
}

fn build_hex_tex_coord(map_size: Size2<MInt>) -> ~[TextureCoord] {
    let mut vertex_data = ~[];
    for _ in MapPosIter::new(map_size) {
        for _ in range(0, 6) {
            vertex_data.push(Vec2{x: 0.0, y: 0.0});
            vertex_data.push(Vec2{x: 1.0, y: 0.0});
            vertex_data.push(Vec2{x: 0.5, y: 0.5});
        }
    }
    vertex_data
}

fn read_win_size(config_path: &str) -> Size2<MInt> {
    let path = Path::new(config_path);
    let json = json::from_str(read_file(&path)).unwrap();
    let mut decoder = json::Decoder::new(json);
    let size: Size2<MInt> = Decodable::decode(&mut decoder);
    size
}

fn init_win(win_size: Size2<MInt>) -> glfw::Window {
    glfw::set_error_callback(~glfw::LogErrorHandler);
    let init_status = glfw::init();
    if !init_status.is_ok() {
        fail!("Failed to initialize GLFW");
    }
    let win = glfw::Window::create(
        win_size.w as u32,
        win_size.h as u32,
        "Marauder",
        glfw::Windowed,
    ).unwrap();
    win.make_context_current();
    win.set_all_polling(true);
    win
}

fn get_scenes(players_count: MInt) -> HashMap<PlayerId, Scene> {
    let mut m = HashMap::new();
    for i in range(0, players_count) {
        m.insert(PlayerId(i), HashMap::new());
    }
    m
}

fn get_game_states(players_count: MInt) -> HashMap<PlayerId, GameState> {
    let mut m = HashMap::new();
    for i in range(0, players_count) {
        m.insert(PlayerId(i), GameState::new());
    }
    m
}

fn get_pathfinders(
    players_count: MInt,
    map_size: Size2<MInt>,
) -> HashMap<PlayerId, Pathfinder> {
    let mut m = HashMap::new();
    for i in range(0, players_count) {
        m.insert(PlayerId(i), Pathfinder::new(map_size));
    }
    m
}

fn get_map_mesh(geom: &Geom, map_size: Size2<MInt>, shader: &Shader) -> Mesh {
    let tex = Texture::new(~"data/floor.png");
    let mut mesh = Mesh::new(build_hex_mesh(geom, map_size));
    mesh.set_texture(tex, build_hex_tex_coord(map_size));
    mesh.prepare(shader);
    mesh
}

fn load_unit_mesh(shader: &Shader) -> Mesh {
    let tex = Texture::new(~"data/tank.png");
    let obj = obj::Model::new("data/tank.obj");
    let mut mesh = Mesh::new(obj.build());
    mesh.set_texture(tex, obj.build_tex_coord());
    mesh.prepare(shader);
    mesh
}

pub struct Visualizer<'a> {
    shader: Shader,
    map_mesh: Mesh,
    unit_mesh: Mesh,
    mvp_mat_id: MatId,
    win: glfw::Window,
    mouse_pos: Point2<MFloat>,
    camera: Camera,
    tile_picker: ~TilePicker,
    selected_tile_pos: Option<MapPos>,
    selected_unit_id: Option<UnitId>,
    geom: Geom,
    scenes: HashMap<PlayerId, Scene>,
    core: ~core::Core<'a>,
    event: Option<core::Event>,
    event_visualizer: Option<~EventVisualizer>,
    game_state: HashMap<PlayerId, GameState>,
    pathfinders: HashMap<PlayerId, Pathfinder>,
}

impl<'a> Visualizer<'a> {
    pub fn new() -> ~Visualizer {
        let players_count = 2;
        let win_size = read_win_size("config.json");
        let win = init_win(win_size);
        load_gl_funcs_with(glfw::get_proc_address);
        init_opengl();
        let geom = Geom::new();
        let core = core::Core::new();
        let map_size = core.map_size();
        let tile_picker = TilePicker::new(
            win_size, &geom, core.map_size());
        let shader = Shader::new("normal.vs.glsl", "normal.fs.glsl");
        let mvp_mat_id = MatId(shader.get_uniform("mvp_mat"));
        let vis = ~Visualizer {
            map_mesh: get_map_mesh(&geom, map_size, &shader),
            unit_mesh: load_unit_mesh(&shader),
            mvp_mat_id: mvp_mat_id,
            shader: shader,
            win: win,
            mouse_pos: Vec2::zero(),
            camera: Camera::new(),
            tile_picker: tile_picker,
            selected_tile_pos: None,
            selected_unit_id: None,
            geom: geom,
            core: core,
            event_visualizer: None,
            event: None,
            scenes: get_scenes(players_count),
            game_state: get_game_states(players_count),
            pathfinders: get_pathfinders(players_count, map_size),
        };
        vis
    }

    fn win<'a>(&'a self) -> &'a glfw::Window {
        &self.win
    }

    fn scene<'a>(&'a self) -> &'a Scene {
        self.scenes.get(&self.core.player_id())
    }

    fn unit_at_opt(&'a self, pos: MapPos) -> Option<&'a core::Unit> {
        let mut res = None;
        let id = self.core.player_id();
        for (_, unit) in self.game_state.get(&id).units.iter() {
            if unit.pos == pos {
                res = Some(unit);
                break;
            }
        }
        res
    }

    fn draw_units(&self) {
        for (_, unit) in self.scene().iter() {
            let m = tr(self.camera.mat(), unit.pos);
            uniform_mat4f(self.mvp_mat_id, &m);
            self.unit_mesh.draw(&self.shader);
        }
    }

    fn draw_map(&self) {
        uniform_mat4f(self.mvp_mat_id, &self.camera.mat());
        self.map_mesh.draw(&self.shader);
    }

    fn draw(&mut self) {
        set_clear_color(0.3, 0.3, 0.3);
        clear_screen();
        self.shader.activate();
        self.draw_units();
        self.draw_map();
        if !self.event_visualizer.is_none() {
            let scene = self.scenes.get_mut(&self.core.player_id());
            self.event_visualizer.get_mut_ref().draw(&self.geom, scene);
        }
        self.win().swap_buffers();
    }

    pub fn is_running(&self) -> MBool {
        return !self.win().should_close()
    }

    fn end_turn(&mut self) {
        self.core.do_command(core::CommandEndTurn);
        self.selected_unit_id = None;
    }

    fn create_unit(&mut self) {
        let pos_opt = self.selected_tile_pos;
        if pos_opt.is_some() {
            let pos = pos_opt.unwrap();
            if self.unit_at_opt(pos).is_none() {
                let cmd = core::CommandCreateUnit(pos);
                self.core.do_command(cmd);
            }
        }
    }

    fn attack_unit(&mut self) {
        let pos_opt = self.selected_tile_pos;
        if pos_opt.is_some() {
            let pos = pos_opt.unwrap();
            if self.unit_at_opt(pos).is_some() {
                let defender_id = self.unit_at_opt(pos).unwrap().id;
                let cmd = core::CommandAttackUnit(UnitId(0), defender_id);
                self.core.do_command(cmd);
            }
        }
    }

    fn handle_key_event(&mut self, key: glfw::Key) {
        match key {
            glfw::KeyEscape | glfw::KeyQ => {
                self.win().set_should_close(true);
            },
            glfw::KeyUp => self.camera.move(270.0),
            glfw::KeyDown => self.camera.move(90.0),
            glfw::KeyRight => self.camera.move(0.0),
            glfw::KeyLeft => self.camera.move(180.0),
            glfw::KeyMinus => self.camera.zoom += 1.0,
            glfw::KeyEqual => self.camera.zoom -= 1.0,
            _ => {},
        }
        if self.event_visualizer.is_some() {
            return;
        }
        match key {
            glfw::KeyT => self.end_turn(),
            glfw::KeyU => self.create_unit(),
            glfw::KeyA => self.attack_unit(),
            _ => {},
        }
    }

    fn handle_cursor_pos_event(&mut self, pos: Point2<MFloat>) {
        let button = self.win().get_mouse_button(glfw::MouseButtonRight);
        if button == glfw::Press {
            self.camera.z_angle += (self.mouse_pos.x - pos.x) / 2.0;
            self.camera.x_angle += (self.mouse_pos.y - pos.y) / 2.0;
        }
        self.mouse_pos = pos;
    }

    fn handle_mouse_button_event(&mut self) {
        if self.event_visualizer.is_some() {
            return;
        }
        if self.selected_tile_pos.is_some() {
            let pos = self.selected_tile_pos.unwrap();
            if self.unit_at_opt(pos).is_some() {
                let unit_id = self.unit_at_opt(pos).unwrap().id;
                let state = self.game_state.get_mut(&self.core.player_id());
                self.selected_unit_id = Some(unit_id);
                let pf = self.pathfinders.get_mut(&self.core.player_id());
                pf.fill_map(state, state.units.get(&unit_id));
            } else if self.selected_unit_id.is_some() {
                let unit_id = self.selected_unit_id.unwrap();
                let pf = self.pathfinders.get_mut(&self.core.player_id());
                let path = pf.get_path(pos);
                self.core.do_command(core::CommandMove(unit_id, path));
            }
        }
    }

    fn get_events(&mut self) -> ~[glfw::WindowEvent] {
        glfw::poll_events();
        let mut events = ~[];
        for (_, event) in self.win().flush_events() {
            events.push(event);
        }
        events
    }

    fn handle_event(&mut self, event: glfw::WindowEvent) {
        match event {
            glfw::KeyEvent(key, _, glfw::Press, _) => {
                self.handle_key_event(key);
            },
            glfw::CursorPosEvent(x, y) => {
                let p = Vec2{x: x as MFloat, y: y as MFloat};
                self.handle_cursor_pos_event(p);
            },
            glfw::MouseButtonEvent(glfw::MouseButtonLeft, glfw::Press, _) => {
                self.handle_mouse_button_event();
            },
            glfw::SizeEvent(w, h) => {
                set_viewport(Size2{w: w, h: h});
                self.tile_picker.set_win_size(Size2{w: w, h: h});
            },
            _ => {},
        }
    }

    fn handle_events(&mut self) {
        for event in self.get_events().iter() {
            self.handle_event(*event);
        }
    }

    fn pick_tile(&mut self) {
        let mouse_pos = Vec2 {
            x: self.mouse_pos.x as MInt,
            y: self.mouse_pos.y as MInt,
        };
        self.selected_tile_pos =
            self.tile_picker.pick_tile(&self.camera, mouse_pos);
    }

    fn make_event_visualizer(&mut self, event: &core::Event) -> ~EventVisualizer {
        match *event {
            core::EventMove(ref unit_id, ref path) => {
                EventMoveVisualizer::new(*unit_id, path.clone())
            },
            core::EventEndTurn(_, _) => {
                EventEndTurnVisualizer::new()
            },
            core::EventCreateUnit(id, ref pos) => {
                EventCreateUnitVisualizer::new(id, *pos)
            },
            core::EventAttackUnit(attacker_id, defender_id) => {
                EventAttackUnitVisualizer::new(attacker_id, defender_id)
            },
        }
    }

    fn logic(&mut self) {
        if self.event_visualizer.is_none() {
            let event_opt = self.core.get_event();
            if event_opt.is_some() {
                let event = event_opt.unwrap();
                let vis = self.make_event_visualizer(&event);
                self.event = Some(event);
                self.event_visualizer = Some(vis);
                let scene = self.scenes.get_mut(&self.core.player_id());
                self.event_visualizer.get_mut_ref().start(&self.geom, scene);
            }
        } else if self.event_visualizer.get_ref().is_finished() {
            let scene = self.scenes.get_mut(&self.core.player_id());
            self.event_visualizer.get_mut_ref().end(&self.geom, scene);
            let state = self.game_state.get_mut(&self.core.player_id());
            state.apply_event(self.event.get_ref());
            self.event_visualizer = None;
            self.event = None;
            if self.selected_unit_id.is_some() {
                let unit_id = self.selected_unit_id.unwrap();
                let pf = self.pathfinders.get_mut(&self.core.player_id());
                pf.fill_map(state, state.units.get(&unit_id));
            }
        }
    }

    pub fn tick(&mut self) {
        self.handle_events();
        self.logic();
        self.pick_tile();
        self.draw();
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>