use std::{fmt, mem, str::FromStr};
use bitcoin::hashes::Hash;
use derive_more::Deref;
use schemars::JsonSchema;
use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
use vecdb::{Bytes, Formattable};
#[derive(Debug, Deref, Clone, PartialEq, Eq, JsonSchema, Bytes, Hash)]
#[schemars(
example = "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
example = "2bb85f4b004be6da54f766c17c1e855187327112c231ef2ff35ebad0ea67c69e",
example = "9a0b3b8305bb30cacf9e8443a90d53a76379fb3305047fdeaa4e4b0934a2a1ba"
)]
#[repr(C)]
#[schemars(transparent, with = "String")]
pub struct Txid([u8; 32]);
impl Txid {
pub const COINBASE: Self = Self([0u8; 32]);
}
impl From<bitcoin::Txid> for Txid {
#[inline]
fn from(value: bitcoin::Txid) -> Self {
unsafe { mem::transmute(value) }
}
}
impl From<&bitcoin::Txid> for &Txid {
#[inline]
fn from(value: &bitcoin::Txid) -> Self {
unsafe { mem::transmute(value) }
}
}
impl From<Txid> for bitcoin::Txid {
#[inline]
fn from(value: Txid) -> Self {
unsafe { mem::transmute(value) }
}
}
impl From<&Txid> for bitcoin::Txid {
#[inline]
fn from(value: &Txid) -> Self {
bitcoin::Txid::from_slice(&value.0).unwrap()
}
}
impl From<&Txid> for &bitcoin::Txid {
#[inline]
fn from(value: &Txid) -> Self {
unsafe { mem::transmute(value) }
}
}
impl fmt::Display for Txid {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&bitcoin::Txid::from(self).to_string())
}
}
impl FromStr for Txid {
type Err = bitcoin::hashes::hex::HexToArrayError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
bitcoin::Txid::from_str(s).map(Self::from)
}
}
impl Serialize for Txid {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl<'de> Deserialize<'de> for Txid {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
let bitcoin_txid = bitcoin::Txid::from_str(&s).map_err(de::Error::custom)?;
Ok(Self::from(bitcoin_txid))
}
}
impl Formattable for Txid {
fn write_to(&self, buf: &mut Vec<u8>) {
use std::fmt::Write;
let mut s = String::new();
write!(s, "{}", self).unwrap();
buf.extend_from_slice(s.as_bytes());
}
fn fmt_json(&self, buf: &mut Vec<u8>) {
buf.push(b'"');
self.write_to(buf);
buf.push(b'"');
}
}