1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
use std::error::Error;

use crate::serialization::state::Account as ProtoAccount;
use crate::traits::{Decode, Encode, Proto};
use protobuf::Message as ProtoMessage;

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Account {
    pub balance: u64,
    pub nonce: u32,
}

impl Account {
    pub fn new(balance: u64, nonce: u32) -> Self {
        Account { balance, nonce }
    }

    pub fn from_proto(account: &ProtoAccount) -> Self {
        Self {
            balance: account.get_balance(),
            nonce: account.get_nonce(),
        }
    }
}

impl Decode for Account {
    fn decode(buffer: &[u8]) -> Result<Account, Box<Error>> {
        let mut proto_account = ProtoAccount::new();
        proto_account.merge_from_bytes(buffer)?;
        Ok(Account::new(proto_account.balance, proto_account.nonce))
    }
}

impl Proto for Account {
    type ProtoType = ProtoAccount;
    fn to_proto(&self) -> Result<Self::ProtoType, Box<Error>> {
        let mut proto_account = Self::ProtoType::new();
        proto_account.balance = self.balance;
        proto_account.nonce = self.nonce;

        Ok(proto_account)
    }

    fn from_proto(_prototype: &Self::ProtoType) -> Result<Self, Box<Error>> {
        unimplemented!()
    }
}

impl Encode for Account {
    fn encode(&self) -> Result<Vec<u8>, Box<Error>> {
        let proto_account = self.to_proto()?;

        Ok(proto_account.write_to_bytes()?)
    }
}

impl Default for Account {
    fn default() -> Self {
        Self {
            balance: 0u64,
            nonce: 0u32,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn it_makes_a_account() {
        let balance: u64 = 1000;
        let nonce: u32 = 20;
        let account = Account::new(balance, nonce);
        assert_eq!(account.balance, balance);
        assert_eq!(account.nonce, nonce);
    }

    #[test]
    fn it_encodes_like_javascript_for_non_zero() {
        let balance: u64 = 1000;
        let nonce: u32 = 20;
        let account = Account::new(balance, nonce);
        let encoded = account.encode().unwrap();
        let javascript_encoded = vec![8, 232, 7, 16, 20];
        let decoded = Account::decode(&encoded).unwrap();
        assert_eq!(encoded, javascript_encoded);
        assert_eq!(decoded.balance, account.balance);
        assert_eq!(decoded.nonce, account.nonce);
    }

    #[test]
    fn it_encodes_like_javascript_for_zero() {
        let balance: u64 = 1000;
        let nonce: u32 = 0;
        let account = Account::new(balance, nonce);
        let encoded = account.encode().unwrap();
        let javascript_encoded = vec![8, 232, 7, 16, 0];
        let decoded = Account::decode(&encoded).unwrap();
        assert_eq!(encoded, javascript_encoded);
        assert_eq!(decoded.balance, account.balance);
        assert_eq!(decoded.nonce, account.nonce);
    }
}