use alloc::string::{String, ToString};
use core::fmt;
use core::str::FromStr;
use bitcoin::hashes::sha256::Hash as Sha256Hash;
use bitcoin::hashes::Hash;
use bitcoin::secp256k1::XOnlyPublicKey;
use serde_json::{json, Value};
use super::{Kind, Tag};
use crate::Timestamp;
#[derive(Debug, PartialEq, Eq)]
pub enum Error {
Hex(bitcoin::hashes::hex::Error),
Hash(bitcoin::hashes::Error),
}
#[cfg(feature = "std")]
impl std::error::Error for Error {}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Hex(e) => write!(f, "Hex: {e}"),
Self::Hash(e) => write!(f, "Hash: {e}"),
}
}
}
impl From<bitcoin::hashes::hex::Error> for Error {
fn from(e: bitcoin::hashes::hex::Error) -> Self {
Self::Hex(e)
}
}
impl From<bitcoin::hashes::Error> for Error {
fn from(e: bitcoin::hashes::Error) -> Self {
Self::Hash(e)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct EventId(Sha256Hash);
impl EventId {
pub fn new(
pubkey: &XOnlyPublicKey,
created_at: Timestamp,
kind: &Kind,
tags: &[Tag],
content: &str,
) -> Self {
let json: Value = json!([0, pubkey, created_at, kind, tags, content]);
let event_str: String = json.to_string();
Self(Sha256Hash::hash(event_str.as_bytes()))
}
pub fn from_hex<S>(hex: S) -> Result<Self, Error>
where
S: AsRef<str>,
{
Ok(Self(Sha256Hash::from_str(hex.as_ref())?))
}
pub fn from_slice(sl: &[u8]) -> Result<Self, Error> {
Ok(Self(Sha256Hash::from_slice(sl)?))
}
pub fn from_hash(hash: Sha256Hash) -> Self {
Self(hash)
}
pub fn all_zeros() -> Self {
Self(Sha256Hash::all_zeros())
}
pub fn as_bytes(&self) -> &[u8] {
self.as_ref()
}
pub fn to_bytes(self) -> [u8; 32] {
self.0.to_byte_array()
}
pub fn to_hex(&self) -> String {
self.0.to_string()
}
pub fn inner(&self) -> Sha256Hash {
self.0
}
}
impl FromStr for EventId {
type Err = Error;
fn from_str(hex: &str) -> Result<Self, Self::Err> {
Self::from_hex(hex)
}
}
impl AsRef<[u8]> for EventId {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl fmt::LowerHex for EventId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.to_hex())
}
}
impl fmt::Display for EventId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::LowerHex::fmt(self, f)
}
}
impl From<Sha256Hash> for EventId {
fn from(hash: Sha256Hash) -> Self {
Self(hash)
}
}
impl From<EventId> for String {
fn from(event_id: EventId) -> Self {
event_id.to_string()
}
}
impl From<EventId> for Tag {
fn from(event_id: EventId) -> Self {
Tag::event(event_id)
}
}