use crate::{id::Error, RevisionId}; use serde::{de, Serialize, Serializer}; use std::{fmt, ops::Deref, str::FromStr}; #[derive(Clone, Debug, Eq, Ord, Hash, PartialOrd, PartialEq)] /// PaymentID /// /// This is the payment ID. The payment ID has two public members, which is /// basically the transaction which created this payment and the position in the /// transaction. pub struct PaymentId { /// Transaction which created this payment pub transaction: RevisionId, /// This payment position inside the transaction pub position: u16, } impl FromStr for PaymentId { type Err = Error; fn from_str(s: &str) -> Result { let parts: Vec<&str> = s.split(':').collect(); if parts.len() != 2 { return Err(Error::InvalidLength( "payment_id".to_owned(), 2, parts.len(), )); } let transaction = parts[0].try_into()?; let position = parts[1].parse()?; Ok(PaymentId { transaction, position, }) } } impl PaymentId { /// Returns the bytes representation of the PaymentId pub fn bytes(&self) -> [u8; 34] { let mut bytes = [0u8; 34]; bytes[0..32].copy_from_slice(self.transaction.deref()); bytes[32..34].copy_from_slice(&self.position.to_be_bytes()); bytes } } impl Serialize for PaymentId { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let serialized = self.to_string(); serializer.serialize_str(&serialized) } } impl ToString for PaymentId { fn to_string(&self) -> String { format!("{}:{}", self.transaction, self.position) } } struct PaymentIdVisitor; impl<'de> de::Visitor<'de> for PaymentIdVisitor { type Value = PaymentId; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a string in the format 'transaction_id:position'") } fn visit_str(self, value: &str) -> Result where E: de::Error, { value .parse() .map_err(|e: Error| E::custom(format!("Invalid payment ID: {}", e))) } } impl<'de> de::Deserialize<'de> for PaymentId { fn deserialize(deserializer: D) -> Result where D: de::Deserializer<'de>, { deserializer.deserialize_str(PaymentIdVisitor) } }