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
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::{fmt, str::FromStr};

/// Address with the appropriate implementation for Serde API and
/// Display/FromStr interfaces.
///
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Address(pub String, pub chain_addr::Address);

/* ---------------- Display ------------------------------------------------ */

impl fmt::Display for Address {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        chain_addr::AddressReadable::from_address(&self.0, &self.1).fmt(f)
    }
}

impl FromStr for Address {
    type Err = chain_addr::Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        s.parse()
            .map(|v: chain_addr::AddressReadable| Address(v.get_prefix(), v.to_address()))
    }
}

/* ---------------- AsRef -------------------------------------------------- */

impl AsRef<chain_addr::Address> for Address {
    fn as_ref(&self) -> &chain_addr::Address {
        &self.1
    }
}
/* ---------------- Conversion --------------------------------------------- */

impl From<chain_addr::Address> for Address {
    fn from(v: chain_addr::Address) -> Self {
        Address("ca".to_owned(), v)
    }
}

impl From<Address> for chain_addr::Address {
    fn from(v: Address) -> Self {
        v.1
    }
}

/* ------------------- Serde ----------------------------------------------- */

impl Serialize for Address {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        if serializer.is_human_readable() {
            let address = self.to_string();
            serializer.serialize_str(&address)
        } else {
            let bytes = self.1.to_bytes();
            serializer.serialize_bytes(&bytes)
        }
    }
}

impl<'de> Deserialize<'de> for Address {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        if deserializer.is_human_readable() {
            let s: String = String::deserialize(deserializer)?;
            chain_addr::AddressReadable::from_string_anyprefix(&s)
                .map_err(serde::de::Error::custom)
                .map(|a| Address(a.get_prefix(), a.to_address()))
        } else {
            let b: Vec<u8> = Vec::deserialize(deserializer)?;
            chain_addr::Address::from_bytes(&b)
                .map_err(serde::de::Error::custom)
                .map(Address::from)
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::crypto::key::KeyPair;
    use quickcheck::{Arbitrary, Gen, TestResult};

    impl Arbitrary for Address {
        fn arbitrary<G>(g: &mut G) -> Self
        where
            G: Gen,
        {
            let kp: KeyPair<chain_crypto::Ed25519> = KeyPair::arbitrary(g);
            let pk: chain_crypto::PublicKey<chain_crypto::Ed25519> =
                kp.identifier().into_public_key();

            let (discrimination, prefix) = if bool::arbitrary(g) {
                (chain_addr::Discrimination::Production, "ca".to_owned())
            } else {
                (chain_addr::Discrimination::Test, "ca".to_owned())
            };

            let kind = match u8::arbitrary(g) % 3 {
                0 => chain_addr::Kind::Single(pk),
                1 => chain_addr::Kind::Account(pk),
                2 => chain_addr::Kind::Group(pk.clone(), pk),
                _ => unreachable!(),
            };

            let address = chain_addr::Address(discrimination, kind);

            Address(prefix, address)
        }
    }

    quickcheck! {
        fn address_display_parse(address: Address) -> TestResult {
            let s = address.to_string();
            let address_dec: Address = s.parse().unwrap();

            TestResult::from_bool(address == address_dec)
        }

        fn address_serde_human_readable_encode_decode(address: Address) -> TestResult {
            let s = serde_yaml::to_string(&address).unwrap();
            let address_dec: Address = serde_yaml::from_str(&s).unwrap();

            TestResult::from_bool(address == address_dec)
        }

        fn address_serde_binary_encode_decode(address: Address) -> TestResult {
            let s = bincode::serialize(&address).unwrap();
            let address_dec: Address = bincode::deserialize(&s).unwrap();

            TestResult::from_bool(address == address_dec)
        }
    }
}