use chrono::ParseError as ChronoParseError;
use serde::{Deserialize, Serialize};
use snafu::Snafu;
use crate::{
ABIProvider, Action, ActionError, Extensions, JsonValue,
TransactionId, TimePointSec, VarUint32, ABISerializable,
convert::{variant_to_object, variant_to_str, variant_to_uint, ConversionError},
impl_auto_error_conversion, with_location,
};
extern crate self as kudu;
#[with_location]
#[derive(Debug, Snafu)]
pub enum TransactionError {
#[snafu(display("unknown field: '{field}'"))]
UnknownField { field: String },
#[snafu(display("cannot convert field to required target type"))]
Conversion { source: ConversionError },
#[snafu(display("cannot parse date/time"))]
DateTimeParse { source: ChronoParseError },
#[snafu(display("invalid action"))]
InvalidAction { source: ActionError },
#[snafu(display("could not match JSON object to transaction"))]
FromJson { source: serde_json::Error },
}
impl_auto_error_conversion!(ChronoParseError, TransactionError, DateTimeParseSnafu);
impl_auto_error_conversion!(ConversionError, TransactionError, ConversionSnafu);
impl_auto_error_conversion!(ActionError, TransactionError, InvalidActionSnafu);
impl_auto_error_conversion!(serde_json::Error, TransactionError, FromJsonSnafu);
#[derive(Eq, Hash, PartialEq, Debug, Clone, Default, Serialize, Deserialize, ABISerializable)]
pub struct Transaction {
pub expiration: TimePointSec,
pub ref_block_num: u16,
pub ref_block_prefix: u32,
pub max_net_usage_words: VarUint32,
pub max_cpu_usage_ms: u8,
pub delay_sec: VarUint32,
pub context_free_actions: Vec<Action>,
pub actions: Vec<Action>,
pub transaction_extensions: Extensions,
}
impl Transaction {
pub fn id() -> TransactionId {
todo!(); }
pub fn from_json(
abi_provider: Option<&ABIProvider>,
tx: &JsonValue
) -> Result<Transaction, TransactionError> {
let mut result = Transaction::default();
for (field, value) in variant_to_object(tx)?.iter() {
match field.as_str() {
"expiration" => result.expiration = variant_to_str(value)?.parse()?,
"ref_block_num" => result.ref_block_num = variant_to_uint(value)?,
"ref_block_prefix" => result.ref_block_prefix = variant_to_uint(value)?,
"max_cpu_usage_ms" => result.max_cpu_usage_ms = variant_to_uint(value)?,
"max_net_usage_words" => result.max_net_usage_words = variant_to_uint::<u32>(value)?.into(),
"delay_sec" => result.delay_sec = variant_to_uint::<u32>(value)?.into(),
"context_free_actions" => result.context_free_actions = Action::from_json_array(abi_provider, value)?,
"actions" => result.actions = Action::from_json_array(abi_provider, value)?,
"transaction_extensions" => result.transaction_extensions = serde_json::from_value(value.clone())?,
other => UnknownFieldSnafu { field: other }.fail()?,
}
}
Ok(result)
}
}