id.rs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. use serde::{Deserialize, Deserializer, Serialize};
  2. use sha2::{Digest, Sha256};
  3. use std::fmt::Display;
  4. use std::str::FromStr;
  5. #[derive(thiserror::Error, Debug)]
  6. pub enum Error {
  7. #[error("Invalid length for {0}: {1} (expected: {2})")]
  8. InvalidLength(String, usize, usize),
  9. #[error("Unknown prefix {0}")]
  10. UnknownPrefix(String),
  11. }
  12. macro_rules! Id {
  13. ($id:ident, $suffix:expr) => {
  14. #[derive(Clone, Debug, Eq, PartialOrd, Ord, Hash, PartialEq)]
  15. pub struct $id {
  16. bytes: [u8; 32],
  17. }
  18. impl $id {
  19. pub fn new(bytes: [u8; 32]) -> Self {
  20. Self { bytes }
  21. }
  22. }
  23. impl FromStr for $id {
  24. type Err = Error;
  25. fn from_str(value: &str) -> Result<Self, Self::Err> {
  26. Ok(Self::try_from(value).unwrap_or_else(|_| {
  27. let mut hasher = Sha256::new();
  28. hasher.update(&value);
  29. Self {
  30. bytes: hasher.finalize().into(),
  31. }
  32. }))
  33. }
  34. }
  35. impl Serialize for $id {
  36. fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  37. where
  38. S: serde::Serializer,
  39. {
  40. serializer.collect_str(&self)
  41. }
  42. }
  43. impl<'de> Deserialize<'de> for $id {
  44. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  45. where
  46. D: Deserializer<'de>,
  47. {
  48. let s = String::deserialize(deserializer)?;
  49. // Use FromStr to parse the string and construct the struct
  50. $id::from_str(&s).map_err(serde::de::Error::custom)
  51. }
  52. }
  53. impl TryFrom<&str> for $id {
  54. type Error = Error;
  55. fn try_from(value: &str) -> Result<Self, Self::Error> {
  56. if $suffix.len() + 64 != value.len() {
  57. return Err(Error::InvalidLength(
  58. stringify!($id).to_owned(),
  59. value.len(),
  60. $suffix.len() + 64,
  61. ));
  62. }
  63. if !value.starts_with($suffix) {
  64. return Err(Error::InvalidLength(
  65. stringify!($id).to_owned(),
  66. value.len(),
  67. $suffix.len() + 64,
  68. ));
  69. }
  70. let bytes = hex::decode(&value[$suffix.len()..]).map_err(|_| {
  71. Error::InvalidLength(stringify!($id).to_owned(), value.len(), 32)
  72. })?;
  73. bytes.try_into()
  74. }
  75. }
  76. impl TryFrom<&[u8]> for $id {
  77. type Error = Error;
  78. fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
  79. if value.len() != 32 {
  80. return Err(Error::InvalidLength(
  81. stringify!($id).to_owned(),
  82. value.len(),
  83. 32,
  84. ));
  85. }
  86. let mut bytes = [0u8; 32];
  87. bytes.copy_from_slice(&value);
  88. Ok(Self { bytes })
  89. }
  90. }
  91. impl TryFrom<Vec<u8>> for $id {
  92. type Error = Error;
  93. fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
  94. if value.len() != 32 {
  95. return Err(Error::InvalidLength(
  96. stringify!($id).to_owned(),
  97. value.len(),
  98. 32,
  99. ));
  100. }
  101. let mut bytes = [0u8; 32];
  102. bytes.copy_from_slice(&value);
  103. Ok(Self { bytes })
  104. }
  105. }
  106. impl Display for $id {
  107. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  108. write!(f, "{}{}", $suffix, hex::encode(self.bytes))
  109. }
  110. }
  111. impl AsRef<[u8]> for $id {
  112. fn as_ref(&self) -> &[u8] {
  113. &self.bytes
  114. }
  115. }
  116. impl AsRef<[u8; 32]> for $id {
  117. fn as_ref(&self) -> &[u8; 32] {
  118. &self.bytes
  119. }
  120. }
  121. impl std::ops::Deref for $id {
  122. type Target = [u8; 32];
  123. fn deref(&self) -> &Self::Target {
  124. &self.bytes
  125. }
  126. }
  127. };
  128. }
  129. Id!(AccountId, "account");
  130. Id!(TransactionId, "tx");
  131. #[derive(Debug)]
  132. pub enum AnyId {
  133. Account(AccountId),
  134. Transaction(TransactionId),
  135. }
  136. impl FromStr for AnyId {
  137. type Err = Error;
  138. fn from_str(value: &str) -> Result<Self, Self::Err> {
  139. if value.starts_with("account") {
  140. Ok(Self::Account(value.parse()?))
  141. } else if value.starts_with("tx") {
  142. Ok(Self::Transaction(value.parse()?))
  143. } else {
  144. Err(Error::UnknownPrefix(value.to_owned()))
  145. }
  146. }
  147. }
  148. impl<'de> Deserialize<'de> for AnyId {
  149. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  150. where
  151. D: Deserializer<'de>,
  152. {
  153. let s = String::deserialize(deserializer)?;
  154. AnyId::from_str(&s).map_err(serde::de::Error::custom)
  155. }
  156. }
  157. #[cfg(test)]
  158. mod test {
  159. use super::*;
  160. #[test]
  161. fn from_random_data() {
  162. let id = "something".parse::<AccountId>().expect("hashed value");
  163. let id_str = id.to_string();
  164. let id_bin: &[u8] = id.as_ref();
  165. assert_eq!(71, id_str.len());
  166. assert_eq!(
  167. <&str as TryInto<AccountId>>::try_into(id_str.as_str()).expect("valid"),
  168. id
  169. );
  170. assert_eq!(
  171. <Vec<u8> as TryInto<AccountId>>::try_into(id_bin.to_owned()).expect("valid"),
  172. id
  173. );
  174. assert_eq!(
  175. <&[u8] as TryInto<AccountId>>::try_into(id_bin).expect("valid"),
  176. id
  177. );
  178. }
  179. }