// SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2023 Snowfork use sp_core::U256; use core::fmt::Formatter; use serde::{Deserialize, Deserializer}; // helper to deserialize arbitrary arrays like [T; N] pub mod arrays { use std::{convert::TryInto, marker::PhantomData}; use serde::{ de::{SeqAccess, Visitor}, ser::SerializeTuple, Deserialize, Deserializer, Serialize, Serializer, }; pub fn serialize( data: &[T; N], ser: S, ) -> Result { let mut s = ser.serialize_tuple(N)?; for item in data { s.serialize_element(item)?; } s.end() } struct ArrayVisitor(PhantomData); impl<'de, T, const N: usize> Visitor<'de> for ArrayVisitor where T: Deserialize<'de>, { type Value = [T; N]; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { formatter.write_str(&format!("an array of length {}", N)) } #[inline] fn visit_seq(self, mut seq: A) -> Result where A: SeqAccess<'de>, { // can be optimized using MaybeUninit let mut data = Vec::with_capacity(N); for _ in 0..N { match (seq.next_element())? { Some(val) => data.push(val), None => return Err(serde::de::Error::invalid_length(N, &self)), } } match data.try_into() { Ok(arr) => Ok(arr), Err(_) => unreachable!(), } } } pub fn deserialize<'de, D, T, const N: usize>(deserializer: D) -> Result<[T; N], D::Error> where D: Deserializer<'de>, T: Deserialize<'de>, { deserializer.deserialize_tuple(N, ArrayVisitor::(PhantomData)) } } pub(crate) fn from_hex_to_bytes<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { let s = String::deserialize(deserializer)?; let str_without_0x = match s.strip_prefix("0x") { Some(val) => val, None => &s, }; let hex_bytes = match hex::decode(str_without_0x) { Ok(bytes) => bytes, Err(e) => return Err(serde::de::Error::custom(e.to_string())), }; Ok(hex_bytes) } pub(crate) fn from_int_to_u256<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { let number = u128::deserialize(deserializer)?; Ok(U256::from(number)) } pub struct HexVisitor(); impl<'de, const LENGTH: usize> serde::de::Visitor<'de> for HexVisitor { type Value = [u8; LENGTH]; fn expecting(&self, formatter: &mut Formatter) -> sp_std::fmt::Result { formatter.write_str("a hex string with an '0x' prefix") } fn visit_str(self, v: &str) -> Result where E: serde::de::Error, { let stripped = match v.strip_prefix("0x") { Some(stripped) => stripped, None => v, }; let decoded = match hex::decode(stripped) { Ok(decoded) => decoded, Err(e) => return Err(serde::de::Error::custom(e.to_string())), }; if decoded.len() != LENGTH { return Err(serde::de::Error::custom("publickey expected to be 48 characters")) } let data: Self::Value = decoded .try_into() .map_err(|_e| serde::de::Error::custom("hex data has unexpected length"))?; Ok(data) } }