1use crate::error::{Error, Result};
2use crate::utils::{decode_base58, encode_issued_currency_amount, encode_variable_length};
3use std::collections::HashMap;
4
5pub enum Field {}
6
7pub trait ToTypeCode {
8 fn to_type_code() -> u16;
9}
10
11macro_rules! type_code {
12 ($name: ident, $type_code: expr) => {
13 impl ToTypeCode for $name {
14 fn to_type_code() -> u16 {
15 $type_code
16 }
17 }
18 };
19}
20
21type_code!(Hash128, 4);
24type_code!(Blob, 7);
25type_code!(AccountID, 8);
26type_code!(Amount, 6);
27type_code!(Hash256, 5);
28type_code!(u8, 16);
29type_code!(Vector256, 19);
30type_code!(STObject, 14);
31type_code!(Hash160, 17);
34type_code!(u16, 1);
37type_code!(u64, 3);
39type_code!(u32, 2);
40type_code!(STArray, 15);
41
42#[derive(Debug, Clone)]
43pub enum Value {
44 Hash128(String),
45 Blob(Blob),
46 AccountID(String),
47 Amount(Amount),
48 Hash256(Hash256),
49 UInt8(u8),
50 Vector256(Vector256),
51 STObject(STObject),
52 Unknown,
53 Transaction(u16),
54 Hash160(Hash160),
55 PathSet,
56 LedgerEntry,
57 UInt16(u16),
58 NotPresent,
59 UInt64(u64),
60 UInt32(u32),
61 STArray(Vec<Value>),
62}
63
64impl Value {
65 pub fn to_bytes(&self) -> Result<Vec<u8>> {
66 match self {
67 Self::AccountID(account_id) => {
68 let address = decode_base58(account_id, &[0x0])?;
69 let length = encode_variable_length(address.len());
70 Ok([length, address].concat())
71 }
72 Self::Amount(amount) => amount.to_bytes(),
73 Self::UInt8(u) => Ok(u.to_be_bytes().to_vec()),
74 Self::UInt16(u) => Ok(u.to_be_bytes().to_vec()),
75 Self::UInt32(u) => Ok(u.to_be_bytes().to_vec()),
76 Self::UInt64(u) => Ok(u.to_be_bytes().to_vec()),
77 Self::Blob(blob) => {
78 let data = hex::decode(&blob.0).unwrap();
79 let length = encode_variable_length(data.len());
80 Ok([length, data].concat())
81 }
82 Self::Transaction(tx) => Ok(tx.to_be_bytes().to_vec()),
83 Self::Hash256(hash) => Ok(hash.to_bytes().to_vec()),
84 Self::Vector256(v) => {
85 let data: Vec<u8> =
86 v.0.iter()
87 .map(|h| hex::decode(&h.0).unwrap().to_vec())
88 .flatten()
89 .collect();
90 let length = encode_variable_length(data.len());
91 Ok([length, data].concat())
92 }
93 _ => {
94 unimplemented!()
95 }
96 }
97 }
98}
99
100#[derive(Debug, Clone)]
101pub struct Hash160(pub String);
102
103#[derive(Debug, Clone)]
104pub struct Hash128(pub String);
105
106#[derive(Debug, Clone)]
107pub struct Hash256(pub String);
108
109impl Hash256 {
110 pub fn to_bytes(&self) -> Vec<u8> {
111 hex::decode(&self.0).unwrap().to_vec()
112 }
113}
114
115#[derive(Debug, Clone)]
116pub struct AccountID([u8; 20]);
117
118impl AccountID {
119 pub fn from_str(s: &str) -> Result<AccountID> {
120 decode_base58(s, &[0x00]).map(|bytes| {
121 if bytes.len() == 20 {
122 return Ok(Self(bytes.try_into().map_err(|_| Error::InvalidAddress)?));
123 }
124 Err(Error::InvalidAddress)
125 })?
126 }
127}
128
129#[derive(Debug, Clone)]
130pub enum Amount {
131 XRP(u64),
132 IssuedCurrency {
133 value: String,
134 currency: String,
135 issuer: String,
136 },
137}
138
139impl Amount {
140 pub fn to_bytes(&self) -> Result<Vec<u8>> {
141 match self {
142 Self::XRP(amount) => Ok((amount | 0x4000000000000000u64).to_be_bytes().to_vec()),
143 Self::IssuedCurrency {
144 value,
145 currency,
146 issuer,
147 } => encode_issued_currency_amount(&value, ¤cy, &issuer),
148 }
149 }
150}
151
152#[derive(Debug, Clone)]
153pub struct STObject(HashMap<String, Value>);
154
155#[derive(Debug, Clone)]
156pub struct Blob(pub String);
157
158#[derive(Debug, Clone)]
159pub struct STArray(Vec<Value>);
160
161#[derive(Debug, Clone)]
162pub struct Vector256(pub Vec<Hash256>);