stratum_hns_types/
submit.rs1use encodings::FromHex;
2use extended_primitives::Buffer;
3use serde::de::{self, SeqAccess, Visitor};
4use serde::{Deserialize, Deserializer};
5use serde_tuple::*;
6use std::fmt;
7use stratum_types::traits::Submit as SubmitTrait;
8
9#[derive(Serialize_tuple, Clone, Debug, Default)]
11pub struct Submit {
12 pub username: String,
13 pub job_id: String,
14 pub nonce_2: Buffer,
15 pub timestamp: u64,
16 pub nonce: u32,
17 pub mask: Option<Buffer>,
18}
19
20impl SubmitTrait for Submit {
21 fn username(&self) -> String {
22 self.username.clone()
23 }
24}
25
26impl<'de> Deserialize<'de> for Submit {
27 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
28 where
29 D: Deserializer<'de>,
30 {
31 struct SubmitVisitor;
32 use serde::de::Error;
33
34 #[derive(Deserialize)]
35 #[serde(untagged)]
36 enum StringOrInt {
37 String(String),
38 Int(u64),
39 }
40
41 impl<'de> Visitor<'de> for SubmitVisitor {
47 type Value = Submit;
48
49 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
50 formatter.write_str("struct Submit")
51 }
52
53 fn visit_seq<V>(self, mut seq: V) -> Result<Submit, V::Error>
54 where
55 V: SeqAccess<'de>,
56 {
57 let username = seq
58 .next_element()?
59 .ok_or_else(|| de::Error::invalid_length(0, &self))?;
60 let job_id = seq
61 .next_element()?
62 .ok_or_else(|| de::Error::invalid_length(1, &self))?;
63 let nonce_2 = seq
64 .next_element()?
65 .ok_or_else(|| de::Error::invalid_length(2, &self))?;
66 let timestamp: StringOrInt = seq
67 .next_element()?
68 .ok_or_else(|| de::Error::invalid_length(3, &self))?;
69 let nonce: StringOrInt = seq
70 .next_element()?
71 .ok_or_else(|| de::Error::invalid_length(4, &self))?;
72
73 let mask = seq.next_element()?;
74
75 if mask.is_some() {
76 let real_timestamp = match timestamp {
77 StringOrInt::String(hex) => {
78 let bytes = Vec::from_hex(hex).map_err(Error::custom)?;
79
80 if bytes.len() == 4 {
81 let mut byte_array = [0u8; 4];
82 byte_array.copy_from_slice(&bytes);
83
84 u32::from_be_bytes(byte_array) as u64
85 } else if bytes.len() == 8 {
86 let mut byte_array = [0u8; 8];
87 byte_array.copy_from_slice(&bytes);
88
89 u64::from_be_bytes(byte_array) as u64
90 } else {
91 return Err(Error::custom("Timestamp out of range"));
92 }
93 }
94 StringOrInt::Int(raw) => raw,
95 };
96
97 let real_nonce = match nonce {
98 StringOrInt::String(hex) => {
99 let bytes = Vec::from_hex(hex).map_err(Error::custom)?;
100
101 if bytes.len() == 4 {
102 let mut byte_array = [0u8; 4];
103 byte_array.copy_from_slice(&bytes);
104
105 u32::from_be_bytes(byte_array)
106 } else if bytes.len() == 8 {
107 let mut byte_array = [0u8; 8];
108 byte_array.copy_from_slice(&bytes);
109
110 let nonce = u64::from_be_bytes(byte_array);
111
112 if nonce <= u32::max_value() as u64 {
113 nonce as u32
114 } else {
115 return Err(Error::custom("Nonce out of range"));
116 }
117 } else {
118 return Err(Error::custom("Nonce out of range"));
119 }
120 }
121 StringOrInt::Int(raw) => raw as u32,
122 };
123
124 Ok(Submit {
125 username,
126 job_id,
127 nonce_2,
128 timestamp: real_timestamp,
129 nonce: real_nonce,
130 mask,
131 })
132 } else {
133 let real_timestamp = match timestamp {
134 StringOrInt::String(raw_time) => raw_time.parse().map_err(Error::custom)?,
135 StringOrInt::Int(raw) => raw,
136 };
137
138 let real_nonce = match nonce {
139 StringOrInt::String(raw_nonce) => {
140 raw_nonce.parse().map_err(Error::custom)?
141 }
142 StringOrInt::Int(raw) => raw as u32,
143 };
144
145 Ok(Submit {
146 username,
147 job_id,
148 nonce_2,
149 timestamp: real_timestamp,
150 nonce: real_nonce,
151 mask,
152 })
153 }
154 }
155 }
156
157 deserializer.deserialize_seq(SubmitVisitor)
158 }
159}