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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
use std::{convert::TryFrom, default::Default, mem};

use byteorder::{ByteOrder, LittleEndian};
use bytes::{Bytes, BytesMut};
use derive_more::From;
use prost::Message;

use crate::{
    codec::{CodecError, ProtocolCodecSync},
    field, impl_default_bytes_codec_for,
    types::primitive as protocol_primitive,
    ProtocolError, ProtocolResult,
};

// #####################
// Protobuf
// #####################

// TODO: change to Amount?
#[derive(Clone, Message)]
pub struct Balance {
    #[prost(bytes, tag = "1")]
    pub value: Vec<u8>,
}

#[derive(Clone, Message, From)]
pub struct Hash {
    #[prost(bytes, tag = "1")]
    pub value: Vec<u8>,
}

#[derive(Clone, Message, From)]
pub struct MerkleRoot {
    #[prost(message, tag = "1")]
    pub value: Option<Hash>,
}

#[derive(Clone, Message, From)]
pub struct Address {
    #[prost(bytes, tag = "1")]
    pub value: Vec<u8>,
}

// #####################
// Conversion
// #####################

// Balance

impl From<protocol_primitive::Balance> for Balance {
    fn from(balance: protocol_primitive::Balance) -> Balance {
        let value = balance.to_bytes_be();
        Balance { value }
    }
}

impl TryFrom<Balance> for protocol_primitive::Balance {
    type Error = ProtocolError;

    fn try_from(ser_balance: Balance) -> Result<protocol_primitive::Balance, Self::Error> {
        Ok(protocol_primitive::Balance::from_bytes_be(
            &ser_balance.value,
        ))
    }
}

// Hash

impl From<protocol_primitive::Hash> for Hash {
    fn from(hash: protocol_primitive::Hash) -> Hash {
        let value = hash.as_bytes().to_vec();

        Hash { value }
    }
}

impl TryFrom<Hash> for protocol_primitive::Hash {
    type Error = ProtocolError;

    fn try_from(hash: Hash) -> Result<protocol_primitive::Hash, Self::Error> {
        let bytes = Bytes::from(hash.value);

        protocol_primitive::Hash::from_bytes(bytes)
    }
}

// Address
impl From<protocol_primitive::Address> for Address {
    fn from(address: protocol_primitive::Address) -> Address {
        let value = address.as_bytes().to_vec();

        Address { value }
    }
}

impl TryFrom<Address> for protocol_primitive::Address {
    type Error = ProtocolError;

    fn try_from(address: Address) -> Result<protocol_primitive::Address, Self::Error> {
        let bytes = Bytes::from(address.value);

        protocol_primitive::Address::from_bytes(bytes)
    }
}

// MerkleRoot

impl From<protocol_primitive::MerkleRoot> for MerkleRoot {
    fn from(root: protocol_primitive::MerkleRoot) -> MerkleRoot {
        let value = Some(Hash::from(root));

        MerkleRoot { value }
    }
}

impl TryFrom<MerkleRoot> for protocol_primitive::MerkleRoot {
    type Error = ProtocolError;

    fn try_from(root: MerkleRoot) -> Result<protocol_primitive::MerkleRoot, Self::Error> {
        let hash = field!(root.value, "MerkleRoot", "value")?;

        protocol_primitive::Hash::try_from(hash)
    }
}

// #####################
// Codec
// #####################

// MerkleRoot and AssetID are just Hash aliases
impl_default_bytes_codec_for!(primitive, [Balance, Hash]);

impl ProtocolCodecSync for u64 {
    fn encode_sync(&self) -> ProtocolResult<Bytes> {
        let mut buf = [0u8; mem::size_of::<u64>()];
        LittleEndian::write_u64(&mut buf, *self);

        Ok(BytesMut::from(buf.as_ref()).freeze())
    }

    fn decode_sync(bytes: Bytes) -> ProtocolResult<Self> {
        Ok(LittleEndian::read_u64(bytes.as_ref()))
    }
}

// #####################
// Util
// #####################

#[allow(dead_code)]
fn ensure_len(real: usize, expect: usize) -> Result<(), CodecError> {
    if real != expect {
        return Err(CodecError::WrongBytesLength { expect, real });
    }

    Ok(())
}