antelope/api/v1/
structs.rs

1use std::collections::HashMap;
2
3use serde::de::{self, Visitor};
4use serde::{Deserialize, Deserializer, Serialize};
5use serde_json::{json, Value};
6use std::fmt;
7
8use crate::chain::abi::ABI;
9use crate::chain::public_key::PublicKey;
10use crate::chain::signature::Signature;
11use crate::chain::{
12    action::{Action, PermissionLevel},
13    asset::{deserialize_asset, Asset},
14    authority::Authority,
15    block_id::{deserialize_block_id, deserialize_optional_block_id, BlockId},
16    checksum::{deserialize_checksum256, Checksum160, Checksum256},
17    name::{deserialize_name, deserialize_optional_name, deserialize_vec_name, Name},
18    time::{deserialize_optional_timepoint, deserialize_timepoint, TimePoint, TimePointSec},
19    transaction::TransactionHeader,
20    varint::VarUint32,
21};
22
23#[derive(Debug)]
24pub enum ClientError<T> {
25    SIMPLE(SimpleError),
26    SERVER(ServerError<T>),
27    HTTP(HTTPError),
28    ENCODING(EncodingError),
29    NETWORK(String),
30}
31
32impl<T> ClientError<T> {
33    pub fn simple(message: String) -> Self {
34        ClientError::SIMPLE(SimpleError { message })
35    }
36
37    pub fn encoding(message: String) -> Self {
38        ClientError::ENCODING(EncodingError { message })
39    }
40
41    pub fn server(error: T) -> Self {
42        ClientError::SERVER(ServerError { error })
43    }
44}
45
46impl<T> From<EncodingError> for ClientError<T> {
47    fn from(value: EncodingError) -> Self {
48        ClientError::ENCODING(value)
49    }
50}
51
52impl<T> From<String> for ClientError<T> {
53    fn from(value: String) -> Self {
54        ClientError::simple(value)
55    }
56}
57
58#[derive(Debug)]
59pub struct SimpleError {
60    pub message: String,
61}
62
63#[derive(Debug)]
64pub struct ServerError<T> {
65    pub error: T,
66}
67
68#[derive(Debug)]
69pub struct HTTPError {
70    pub code: u16,
71    pub message: String,
72}
73
74#[derive(Debug)]
75pub struct EncodingError {
76    pub message: String,
77}
78
79impl EncodingError {
80    pub fn new(message: String) -> Self {
81        EncodingError { message }
82    }
83}
84
85// pub trait ClientError {
86//     fn get_message(&self) -> &str;
87// }
88//
89// pub struct SimpleError {
90//     pub message: str,
91// }
92//
93// impl ClientError for SimpleError {
94//     fn get_message(&self) -> String {
95//         self.message.to_string()
96//     }
97// }
98
99#[derive(Debug, Serialize, Deserialize)]
100pub struct GetInfoResponse {
101    pub server_version: String,
102    #[serde(deserialize_with = "deserialize_checksum256")]
103    pub chain_id: Checksum256,
104    pub head_block_num: u32,
105    pub last_irreversible_block_num: u32,
106    #[serde(deserialize_with = "deserialize_block_id")]
107    pub last_irreversible_block_id: BlockId,
108    #[serde(deserialize_with = "deserialize_block_id")]
109    pub head_block_id: BlockId,
110    #[serde(deserialize_with = "deserialize_timepoint")]
111    pub head_block_time: TimePoint,
112    #[serde(deserialize_with = "deserialize_name")]
113    pub head_block_producer: Name,
114    pub virtual_block_cpu_limit: u64,
115    pub virtual_block_net_limit: u64,
116    pub block_cpu_limit: u64,
117    pub block_net_limit: u64,
118    pub server_version_string: Option<String>,
119    pub fork_db_head_block_num: Option<u32>,
120    #[serde(deserialize_with = "deserialize_optional_block_id")]
121    pub fork_db_head_block_id: Option<BlockId>,
122    pub server_full_version_string: String,
123    #[serde(deserialize_with = "deserialize_number_or_string")]
124    pub total_cpu_weight: String,
125    #[serde(deserialize_with = "deserialize_number_or_string")]
126    pub total_net_weight: String,
127    pub earliest_available_block_num: u32,
128    pub last_irreversible_block_time: String,
129}
130
131impl GetInfoResponse {
132    pub fn get_transaction_header(&self, seconds_ahead: u32) -> TransactionHeader {
133        let expiration = TimePointSec {
134            // head_block_time.elapsed is microseconds, convert to seconds
135            seconds: (self.head_block_time.elapsed / 1000 / 1000) as u32 + seconds_ahead,
136        };
137        let id = self.last_irreversible_block_id.bytes.to_vec();
138        let prefix_array = &id[8..12];
139        let prefix = u32::from_ne_bytes(prefix_array.try_into().unwrap());
140        TransactionHeader {
141            max_net_usage_words: VarUint32::default(),
142            max_cpu_usage_ms: 0,
143            delay_sec: VarUint32::default(),
144            expiration,
145            ref_block_num: (self.last_irreversible_block_num & 0xffff) as u16,
146            ref_block_prefix: prefix,
147        }
148    }
149}
150
151#[derive(Debug, Serialize, Deserialize)]
152pub struct ProcessedTransactionReceipt {
153    pub status: String,
154    pub cpu_usage_us: u32,
155    pub net_usage_words: u32,
156}
157
158#[derive(Debug, Serialize, Deserialize)]
159pub struct ProcessedTransaction {
160    pub id: String,
161    pub block_num: u64,
162    pub block_time: String,
163    pub receipt: ProcessedTransactionReceipt,
164    pub elapsed: u64,
165    pub except: Option<SendTransactionResponseError>,
166    pub net_usage: u32,
167    pub scheduled: bool,
168    pub action_traces: Vec<ActionTrace>,
169    pub account_ram_delta: Option<AccountRamDelta>,
170}
171
172#[derive(Debug, Serialize, Deserialize)]
173pub struct SendTransactionResponseExceptionStackContext {
174    pub level: String,
175    pub file: String,
176    pub line: u32,
177    pub method: String,
178    pub hostname: String,
179    pub thread_name: String,
180    pub timestamp: String,
181}
182
183#[derive(Debug, Serialize, Deserialize)]
184pub struct SendTransactionResponseExceptionStack {
185    pub context: SendTransactionResponseExceptionStackContext,
186    pub format: String,
187    pub data: String, // TODO: create a type for this?
188}
189
190#[derive(Debug, Serialize, Deserialize)]
191pub struct SendTransactionResponseError {
192    pub code: u32,
193    pub name: String,
194    pub what: String,
195    pub stack: Option<Vec<SendTransactionResponseExceptionStack>>,
196    pub details: Vec<SendTransactionResponseErrorDetails>,
197}
198
199impl SendTransactionResponseError {
200    pub fn print_error(&self) {
201        self.details.iter().for_each(|d| println!("{:?}", d));
202    }
203
204    pub fn get_stack(&self) -> String {
205        self.stack
206            .as_ref()
207            .map(|s| {
208                s.iter()
209                    .map(|s| s.format.clone())
210                    .collect::<Vec<String>>()
211                    .join("\n")
212            })
213            .unwrap_or_default()
214    }
215}
216
217#[derive(Debug, Serialize, Deserialize)]
218pub struct SendTransactionResponseErrorDetails {
219    pub message: String,
220    pub file: String,
221    pub line_number: u32,
222    pub method: String,
223}
224
225#[derive(Debug, Serialize, Deserialize)]
226pub struct ErrorResponse {
227    pub code: u16,
228    pub message: String,
229    pub error: SendTransactionResponseError,
230}
231
232#[derive(Debug, Serialize, Deserialize)]
233pub struct SendTransactionResponse {
234    pub transaction_id: String,
235    pub processed: ProcessedTransaction,
236}
237
238#[derive(Debug, Serialize, Deserialize)]
239pub struct ActionTrace {
240    pub action_ordinal: u32,
241    pub creator_action_ordinal: u32,
242    pub closest_unnotified_ancestor_action_ordinal: u32,
243    pub receipt: ActionReceipt,
244    #[serde(deserialize_with = "deserialize_name")]
245    pub receiver: Name,
246    pub act: Action,
247    pub context_free: bool,
248    pub elapsed: u64,
249    pub console: String,
250    pub trx_id: String,
251    pub block_num: u64,
252    pub block_time: String,
253    pub producer_block_id: Option<String>,
254    pub account_ram_deltas: Vec<AccountRamDelta>,
255    pub except: Option<String>,
256    pub error_code: Option<u32>,
257    pub return_value_hex_data: String,
258}
259
260#[derive(Debug, Serialize, Deserialize)]
261pub struct ActionReceipt {
262    #[serde(deserialize_with = "deserialize_name")]
263    pub receiver: Name,
264    pub act_digest: String,
265    pub global_sequence: u64,
266    pub recv_sequence: u64,
267    pub auth_sequence: Vec<AuthSequence>,
268    pub code_sequence: u64,
269    pub abi_sequence: u64,
270}
271
272#[derive(Debug, Serialize, Deserialize)]
273pub struct AuthSequence {
274    #[serde(deserialize_with = "deserialize_name")]
275    pub account: Name,
276    pub sequence: u64,
277}
278
279#[derive(Debug, Serialize, Deserialize, PartialEq)]
280pub struct AccountRamDelta {
281    #[serde(deserialize_with = "deserialize_name")]
282    pub account: Name,
283    pub delta: i64,
284}
285
286#[derive(Debug, Serialize, Deserialize)]
287pub enum IndexPosition {
288    PRIMARY,
289    SECONDARY,
290    TERTIARY,
291    FOURTH,
292    FIFTH,
293    SIXTH,
294    SEVENTH,
295    EIGHTH,
296    NINTH,
297    TENTH,
298}
299
300#[derive(Debug, Serialize, Deserialize)]
301pub enum TableIndexType {
302    NAME(Name),
303    UINT64(u64),
304    UINT128(u128),
305    FLOAT64(f64),
306    CHECKSUM256(Checksum256),
307    CHECKSUM160(Checksum160),
308}
309
310#[derive(Debug, Serialize, Deserialize)]
311pub struct GetTableRowsParams {
312    #[serde(deserialize_with = "deserialize_name")]
313    pub code: Name,
314    #[serde(deserialize_with = "deserialize_name")]
315    pub table: Name,
316    #[serde(deserialize_with = "deserialize_optional_name")]
317    pub scope: Option<Name>,
318    pub lower_bound: Option<TableIndexType>,
319    pub upper_bound: Option<TableIndexType>,
320    pub limit: Option<u32>,
321    pub reverse: Option<bool>,
322    pub index_position: Option<IndexPosition>,
323    pub show_payer: Option<bool>,
324}
325
326impl GetTableRowsParams {
327    pub fn to_json(&self) -> String {
328        let mut req: HashMap<&str, Value> = HashMap::new();
329        req.insert("json", Value::Bool(false));
330        req.insert("code", Value::String(self.code.to_string()));
331        req.insert("table", Value::String(self.table.to_string()));
332
333        let scope = self.scope.unwrap_or(self.code);
334        req.insert("scope", Value::String(scope.to_string()));
335
336        json!(req).to_string()
337    }
338}
339
340pub struct GetTableRowsResponse<T> {
341    pub rows: Vec<T>,
342    pub more: bool,
343    pub ram_payers: Option<Vec<Name>>,
344    pub next_key: Option<TableIndexType>,
345}
346
347#[derive(Debug, Serialize, Deserialize)]
348pub struct AccountObject {
349    #[serde(deserialize_with = "deserialize_name")]
350    pub account_name: Name,
351    pub head_block_num: u32,
352    #[serde(deserialize_with = "deserialize_timepoint")]
353    pub head_block_time: TimePoint,
354    pub privileged: bool,
355    #[serde(deserialize_with = "deserialize_timepoint")]
356    pub last_code_update: TimePoint,
357    #[serde(deserialize_with = "deserialize_timepoint")]
358    pub created: TimePoint,
359    #[serde(deserialize_with = "deserialize_asset")]
360    pub core_liquid_balance: Asset,
361    pub ram_quota: i64,
362    pub net_weight: i64,
363    pub cpu_weight: i64,
364    pub net_limit: AccountResourceLimit,
365    pub cpu_limit: AccountResourceLimit,
366    pub ram_usage: u64,
367    pub permissions: Vec<AccountPermission>,
368    pub total_resources: Option<AccountTotalResources>,
369    pub self_delegated_bandwidth: Option<SelfDelegatedBandwidth>,
370    pub refund_request: Option<AccountRefundRequest>,
371    pub voter_info: Option<AccountVoterInfo>,
372    pub rex_info: Option<AccountRexInfo>,
373    pub subjective_cpu_bill_limit: Option<AccountResourceLimit>,
374    pub eosio_any_linked_actions: Option<Vec<AccountLinkedAction>>,
375}
376
377#[derive(Debug, Serialize, Deserialize)]
378pub struct AccountRexInfo {
379    version: u32,
380    #[serde(deserialize_with = "deserialize_name")]
381    owner: Name,
382    #[serde(deserialize_with = "deserialize_asset")]
383    vote_stake: Asset,
384    #[serde(deserialize_with = "deserialize_asset")]
385    rex_balance: Asset,
386    #[serde(deserialize_with = "deserialize_i64_from_string_or_i64")]
387    matured_rex: i64,
388    rex_maturities: Vec<AccountRexInfoMaturities>,
389}
390#[derive(Debug, Serialize, Deserialize)]
391pub struct AccountRexInfoMaturities {
392    #[serde(
393        deserialize_with = "deserialize_optional_timepoint",
394        default,
395        skip_serializing_if = "Option::is_none"
396    )]
397    key: Option<TimePoint>,
398    #[serde(
399        deserialize_with = "deserialize_optional_i64_from_string",
400        default,
401        skip_serializing_if = "Option::is_none"
402    )]
403    value: Option<i64>,
404    #[serde(
405        deserialize_with = "deserialize_optional_timepoint",
406        default,
407        skip_serializing_if = "Option::is_none"
408    )]
409    first: Option<TimePoint>,
410    #[serde(
411        deserialize_with = "deserialize_optional_i64_from_string",
412        default,
413        skip_serializing_if = "Option::is_none"
414    )]
415    second: Option<i64>,
416}
417
418//export class AccountResourceLimit extends Struct {
419//     @Struct.field('int64') declare used: Int64
420//     @Struct.field('int64') declare available: Int64
421//     @Struct.field('int64') declare max: Int64
422//     @Struct.field('time_point', {optional: true}) declare last_usage_update_time: TimePoint
423//     @Struct.field('int64', {optional: true}) declare current_used: Int64
424// }
425
426#[derive(Debug, Serialize, Deserialize)]
427pub struct AccountResourceLimit {
428    used: i64,
429    available: i64,
430    max: i64,
431    #[serde(
432        deserialize_with = "deserialize_optional_timepoint",
433        default,
434        skip_serializing_if = "Option::is_none"
435    )]
436    last_usage_update_time: Option<TimePoint>,
437    #[serde(
438        deserialize_with = "deserialize_optional_i64_from_string",
439        default,
440        skip_serializing_if = "Option::is_none"
441    )]
442    current_used: Option<i64>,
443}
444
445#[derive(Debug, Serialize, Deserialize)]
446pub struct AccountRefundRequest {
447    #[serde(deserialize_with = "deserialize_name")]
448    owner: Name,
449    #[serde(deserialize_with = "deserialize_timepoint")]
450    request_time: TimePoint,
451    #[serde(deserialize_with = "deserialize_asset")]
452    net_amount: Asset,
453    #[serde(deserialize_with = "deserialize_asset")]
454    cpu_amount: Asset,
455}
456
457#[derive(Debug, Serialize, Deserialize)]
458pub struct ResourceLimit {
459    max: String,
460    available: String,
461    used: String,
462}
463
464#[derive(Debug, Serialize, Deserialize)]
465pub struct AccountTotalResources {
466    #[serde(deserialize_with = "deserialize_name")]
467    owner: Name,
468    #[serde(deserialize_with = "deserialize_asset")]
469    net_weight: Asset,
470    #[serde(deserialize_with = "deserialize_asset")]
471    cpu_weight: Asset,
472    ram_bytes: u64,
473}
474
475#[derive(Debug, Serialize, Deserialize)]
476pub struct SelfDelegatedBandwidth {
477    #[serde(deserialize_with = "deserialize_name")]
478    from: Name,
479    #[serde(deserialize_with = "deserialize_name")]
480    to: Name,
481    #[serde(deserialize_with = "deserialize_asset")]
482    net_weight: Asset,
483    #[serde(deserialize_with = "deserialize_asset")]
484    cpu_weight: Asset,
485}
486
487//@Struct.type('account_permission')
488// export class AccountPermission extends Struct {
489//     @Struct.field('name') declare perm_name: Name
490//     @Struct.field('name') declare parent: Name
491//     @Struct.field(Authority) declare required_auth: Authority
492//     @Struct.field(AccountLinkedAction, {optional: true, array: true})
493//     declare linked_actions: AccountLinkedAction[]
494// }
495
496#[derive(Debug, Serialize, Deserialize)]
497pub struct AccountPermission {
498    #[serde(deserialize_with = "deserialize_name")]
499    parent: Name,
500    #[serde(deserialize_with = "deserialize_name")]
501    perm_name: Name,
502    required_auth: Authority,
503    #[serde(skip_serializing_if = "Option::is_none", default)]
504    pub linked_actions: Option<Vec<AccountLinkedAction>>,
505}
506
507#[derive(Debug, Serialize, Deserialize)]
508pub struct AccountLinkedAction {
509    #[serde(deserialize_with = "deserialize_name")]
510    account: Name,
511    #[serde(deserialize_with = "deserialize_optional_name")]
512    action: Option<Name>,
513}
514
515#[derive(Debug, Serialize, Deserialize)]
516pub struct RequiredAuth {
517    threshold: u32,
518    keys: Vec<Key>,
519    accounts: Vec<Account>,
520    waits: Vec<Wait>,
521}
522
523#[derive(Debug, Serialize, Deserialize)]
524pub struct Wait {
525    wait_sec: u32,
526    weight: u16,
527}
528
529#[derive(Debug, Serialize, Deserialize)]
530pub struct Key {
531    key: String,
532    weight: u16,
533}
534
535#[derive(Debug, Serialize, Deserialize)]
536pub struct Account {
537    weight: u16,
538    permission: PermissionLevel,
539}
540
541#[derive(Debug, Serialize, Deserialize)]
542pub struct AccountVoterInfo {
543    #[serde(deserialize_with = "deserialize_name")]
544    owner: Name,
545    #[serde(deserialize_with = "deserialize_name")]
546    proxy: Name,
547    #[serde(deserialize_with = "deserialize_vec_name")]
548    producers: Vec<Name>,
549    staked: Option<i64>,
550    #[serde(deserialize_with = "deserialize_f64_from_string")]
551    last_vote_weight: f64,
552    #[serde(deserialize_with = "deserialize_f64_from_string")]
553    proxied_vote_weight: f64,
554    #[serde(deserialize_with = "deserialize_bool_from_number")]
555    is_proxy: bool,
556    flags1: Option<u32>,
557    reserved2: u32,
558    reserved3: String,
559}
560
561#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)]
562pub struct ABIResponse {
563    pub account_name: String,
564    pub abi: ABI,
565}
566
567#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
568pub struct GetBlockResponse {
569    pub time_point: TimePoint,
570    pub producer: Name,
571    pub confirmed: u16,
572    pub pevious: BlockId,
573    pub transaction_mroot: Checksum256,
574    pub action_mroot: Checksum256,
575    pub schedule_version: u32,
576    pub new_producers: Option<NewProducers>,
577    pub header_extensions: Option<HeaderExtension>,
578    // pub new_protocol_features: any,
579    pub producer_signature: Signature,
580    pub transactions: Vec<GetBlockResponseTransactionReceipt>,
581    pub block_extensions: Option<Vec<BlockExtension>>,
582    pub id: BlockId,
583    pub block_num: u32,
584    pub ref_block_prefix: u32,
585}
586#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
587pub struct NewProducers {
588    pub version: u32,
589    pub producers: Vec<NewProducersEntry>,
590}
591
592#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
593pub struct NewProducersEntry {
594    pub producer_name: Name,
595    pub block_signing_key: PublicKey,
596}
597
598#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
599pub struct HeaderExtension {
600    pub r#type: u16,
601    pub data: Vec<u8>,
602}
603
604#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
605pub struct GetBlockResponseTransactionReceipt {
606    pub trx: TrxVariant, //TODO: Implement TxVarient
607}
608
609#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
610pub struct TrxVariant {
611    pub id: Checksum256,
612    pub extra: HashMap<String, Value>,
613}
614
615#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
616pub struct BlockExtension {
617    pub r#type: u16,
618    pub data: Vec<u8>,
619}
620
621// impl TrxVariant {
622//     pub fn from(data: serde_json::Value) -> Result<Self, Box<dyn std::error::Error>> {
623//         let id;
624//         let extra: HashMap<String, serde_json::Value>;
625//
626//         match data {
627//             Value::String(s) => {
628//                 id = Checksum256::from(&s)?;
629//                 extra = HashMap::new();
630//             },
631//             Value::Object(obj) => {
632//                 let id_str = obj.get("id")
633//                     .ok_or("id field missing")?
634//                     .as_str()
635//                     .ok_or("id field is not a string")?;
636//                 id = Checksum256::from(id_str)?;
637//                 extra = obj;
638//             },
639//             _ => return Err("Unsupported data type".into()),
640//         }
641//
642//         Ok(TrxVariant { id, extra })
643//     }
644//
645//     pub fn transaction(&self) -> Option<Transaction> {
646//         self.extra.get("packed_trx").and_then(|packed_trx| {
647//             match self.extra.get("compression").and_then(|c| c.as_str()) {
648//                 Some("zlib") => {
649//                     // Decompress using zlib and decode
650//                     let inflated = decompress_zlib(&packed_trx);
651//                     Some(packer::pack(&inflated, Transaction))
652//                 },
653//                 Some("none") => {
654//                     // Directly decode
655//                     Some(packer::pack(packed_trx, Transaction))
656//                 },
657//                 _ => None,
658//             }
659//         })
660//     }
661//
662//     pub fn signatures(&self) -> Option<Vec<Signature>> {
663//         self.extra.get("signatures").and_then(|sigs| {
664//             sigs.as_array().map(|arr| {
665//                 arr.iter().filter_map(|sig| Signature::from(sig)).collect()
666//             })
667//         })
668//     }
669//
670//     pub fn equals(&self, other: &TrxVariant) -> bool {
671//         self.id == other.id
672//     }
673//
674//     pub fn to_json(&self) -> Value {
675//         json!(self.id)
676//     }
677// }
678
679fn deserialize_number_or_string<'de, D>(deserializer: D) -> Result<String, D::Error>
680where
681    D: Deserializer<'de>,
682{
683    let value = Value::deserialize(deserializer)?;
684    match value {
685        Value::Number(num) => Ok(num.to_string()),
686        Value::String(s) => Ok(s),
687        _ => Err(serde::de::Error::custom("expected a number or a string")),
688    }
689}
690
691fn deserialize_f64_from_string<'de, D>(deserializer: D) -> Result<f64, D::Error>
692where
693    D: Deserializer<'de>,
694{
695    struct StringToF64Visitor;
696
697    impl<'de> Visitor<'de> for StringToF64Visitor {
698        type Value = f64;
699
700        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
701            formatter.write_str("a string that can be parsed into a f64")
702        }
703
704        fn visit_str<E>(self, value: &str) -> Result<f64, E>
705        where
706            E: de::Error,
707        {
708            value.parse::<f64>().map_err(de::Error::custom)
709        }
710    }
711
712    deserializer.deserialize_str(StringToF64Visitor)
713}
714
715fn deserialize_bool_from_number<'de, D>(deserializer: D) -> Result<bool, D::Error>
716where
717    D: Deserializer<'de>,
718{
719    struct NumberToBoolVisitor;
720
721    impl<'de> Visitor<'de> for NumberToBoolVisitor {
722        type Value = bool;
723
724        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
725            formatter.write_str("a number representing a boolean (0 or 1)")
726        }
727
728        fn visit_u64<E>(self, value: u64) -> Result<bool, E>
729        where
730            E: de::Error,
731        {
732            match value {
733                0 => Ok(false),
734                1 => Ok(true),
735                _ => Err(E::custom("expected 0 or 1 for boolean")),
736            }
737        }
738    }
739
740    deserializer.deserialize_any(NumberToBoolVisitor)
741}
742
743fn deserialize_i64_from_string_or_i64<'de, D>(deserializer: D) -> Result<i64, D::Error>
744where
745    D: Deserializer<'de>,
746{
747    struct I64OrStringVisitor;
748
749    impl<'de> serde::de::Visitor<'de> for I64OrStringVisitor {
750        type Value = i64;
751
752        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
753            formatter.write_str("an integer or a string representation of an integer")
754        }
755
756        fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
757        where
758            E: serde::de::Error,
759        {
760            value.parse::<i64>().map_err(E::custom)
761        }
762
763        fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
764        where
765            E: serde::de::Error,
766        {
767            Ok(value)
768        }
769
770        fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
771        where
772            E: serde::de::Error,
773        {
774            i64::try_from(value).map_err(|_| E::custom("u64 value too large for i64"))
775        }
776    }
777
778    deserializer.deserialize_any(I64OrStringVisitor)
779}
780
781fn deserialize_optional_i64_from_string<'de, D>(deserializer: D) -> Result<Option<i64>, D::Error>
782where
783    D: Deserializer<'de>,
784{
785    struct StringOrI64Visitor;
786
787    impl<'de> Visitor<'de> for StringOrI64Visitor {
788        type Value = Option<i64>;
789
790        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
791            formatter.write_str(
792                "a string representing a 64-bit signed integer, an actual integer, or null",
793            )
794        }
795
796        fn visit_str<E>(self, value: &str) -> Result<Option<i64>, E>
797        where
798            E: de::Error,
799        {
800            value.parse::<i64>().map(Some).map_err(de::Error::custom)
801        }
802
803        fn visit_i64<E>(self, value: i64) -> Result<Option<i64>, E>
804        where
805            E: de::Error,
806        {
807            Ok(Some(value))
808        }
809
810        fn visit_u64<E>(self, value: u64) -> Result<Option<i64>, E>
811        where
812            E: de::Error,
813        {
814            if value <= i64::MAX as u64 {
815                Ok(Some(value as i64))
816            } else {
817                Err(de::Error::custom("u64 value too large for i64"))
818            }
819        }
820
821        fn visit_none<E>(self) -> Result<Option<i64>, E>
822        where
823            E: de::Error,
824        {
825            Ok(None)
826        }
827
828        fn visit_unit<E>(self) -> Result<Option<i64>, E>
829        where
830            E: de::Error,
831        {
832            Ok(None)
833        }
834    }
835
836    deserializer.deserialize_any(StringOrI64Visitor)
837}