1use super::Error;
2
3use schemars::schema::{Schema, SchemaObject, StringValidation};
4use schemars::gen::SchemaGenerator;
5use schemars::JsonSchema;
6
7use bitcoin_hashes::sha256t::Hash as HashT;
8
9use bitcoin_hashes::Hash as _;
10use bitcoin_hashes::sha256::Midstate;
11use bitcoin_hashes::sha256::HashEngine;
12use bitcoin_hashes::sha256t::Tag as TagTrait;
13
14const MIDSTATE: Midstate = Midstate::hash_tag(b"SIMPLE_CRYPTO");
15
16pub struct Tag {}
17impl TagTrait for Tag {
18 fn engine() -> HashEngine {HashEngine::from_midstate(MIDSTATE, 0)}
19}
20
21pub type BHash = HashT<Tag>;
22
23
24#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
25#[derive(serde_with::SerializeDisplay)]
26#[derive(serde_with::DeserializeFromStr)]
27pub struct Hash {
28 inner: BHash
29}
30
31impl Hash {
32 pub fn to_arr(self) -> [u8; 32] {*self.inner.as_ref()}
33 pub fn all_zeros() -> Self {Hash{inner: BHash::all_zeros()}}
34 pub fn new(inner: BHash) -> Self {Hash{inner}}
35 pub fn to_vec(&self) -> Vec<u8> {
36 self.inner.as_byte_array().to_vec()
37 }
38 pub fn as_bytes(&self) -> &[u8] {self.inner.as_byte_array()}
39 pub fn from_slice(slice: &[u8]) -> Result<Self, Error> {
40 Ok(Hash{inner: BHash::from_slice(slice)?})
41 }
42}
43
44impl std::fmt::Display for Hash {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 write!(f, "{}", hex::encode(self.to_vec()))
47 }
48}
49
50impl std::fmt::Debug for Hash {
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 write!(f, "{}", hex::encode(self.to_vec()))
53 }
54}
55
56impl std::str::FromStr for Hash {
57 type Err = Error;
58
59 fn from_str(s: &str) -> Result<Self, Self::Err> {
60 Hash::from_slice(&hex::decode(s)?)
61 }
62}
63
64impl JsonSchema for Hash {
65 fn schema_name() -> String {"Hash".to_string()}
66 fn json_schema(_gen: &mut SchemaGenerator) -> Schema {
67 Schemas::regex("^(0x|0X)?[a-fA-F0-9]{64}$".to_string())
68 }
69}
70
71pub struct Schemas {}
72impl Schemas {
73 pub fn regex(regex: String) -> Schema {
74 Schema::Object(SchemaObject{
75 string: Some(Box::new(StringValidation {
76 max_length: None,
77 min_length: None,
78 pattern: Some(regex)
79 })),
80 ..Default::default()
81 })
82 }
83}