use pro_env::hash::{
Blake2x256,
CryptoHash,
HashOutput,
};
use pro_primitives::Key;
#[derive(
Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, scale::Encode, scale::Decode,
)]
#[cfg_attr(feature = "std", derive(tetsy_scale_info::TypeInfo))]
pub struct DynamicAllocation(pub(super) u32);
struct Wrap<'a> {
buffer: &'a mut [u8],
len: usize,
}
impl Wrap<'_> {
fn capacity(&self) -> usize {
self.buffer.len()
}
fn len(&self) -> usize {
self.len
}
fn append_bytes(&mut self, bytes: &[u8]) {
debug_assert!(self.len() + bytes.len() <= self.capacity());
let len = self.len;
let bytes_len = bytes.len();
self.buffer[len..(len + bytes_len)].copy_from_slice(bytes);
self.len += bytes_len;
}
}
#[cfg(feature = "std")]
impl<'a> std::io::Write for Wrap<'a> {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.append_bytes(buf);
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
impl<'a> From<&'a mut [u8]> for Wrap<'a> {
fn from(buffer: &'a mut [u8]) -> Self {
Self { buffer, len: 0 }
}
}
#[cfg(not(feature = "std"))]
impl<'a> scale::Output for Wrap<'a> {
fn write(&mut self, bytes: &[u8]) {
self.append_bytes(bytes)
}
fn push_byte(&mut self, byte: u8) {
debug_assert!(self.len() < self.capacity());
self.buffer[self.len] = byte;
self.len += 1;
}
}
impl DynamicAllocation {
pub(super) fn get(self) -> u32 {
self.0
}
pub fn key(self) -> Key {
pub struct EncodeWrapper(u32);
impl scale::Encode for EncodeWrapper {
#[rustfmt::skip]
fn encode_to<O>(&self, output: &mut O)
where
O: scale::Output + ?Sized,
{
<[u8; 21] as scale::Encode>::encode_to(&[
b'D', b'Y', b'N', b'A', b'M', b'I', b'C', b'A', b'L', b'L', b'Y',
b' ',
b'A', b'L', b'L', b'O', b'C', b'A', b'T', b'E', b'D',
], output);
<u32 as scale::Encode>::encode_to(&self.0, output);
}
}
#[rustfmt::skip]
let mut buffer: [u8; 25] = [
b'D', b'Y', b'N', b'A', b'M', b'I', b'C', b'A', b'L', b'L', b'Y',
b' ',
b'A', b'L', b'L', b'O', b'C', b'A', b'T', b'E', b'D',
b'_', b'_', b'_', b'_',
];
{
let mut wrapped = Wrap::from(&mut buffer[21..25]);
<u32 as scale::Encode>::encode_to(&self.0, &mut wrapped);
}
let mut output = <Blake2x256 as HashOutput>::Type::default();
<Blake2x256 as CryptoHash>::hash(&buffer, &mut output);
Key::from(output)
}
}
#[test]
fn get_works() {
let expected_keys = [
b"\
\x0A\x0F\xF5\x30\xBD\x5A\xB6\x67\
\x85\xC9\x74\x6D\x01\x33\xD7\xE1\
\x24\x40\xC4\x67\xA9\xF0\x6D\xCA\
\xE7\xED\x2E\x78\x32\x77\xE9\x10",
b"\
\x11\x5A\xC0\xB2\x29\xA5\x34\x10\
\xB0\xC0\x2D\x47\x49\xDC\x7A\x09\
\xB9\x6D\xF9\x51\xB6\x1D\x4F\x3B\
\x4E\x75\xAC\x3B\x14\x57\x47\x96",
];
assert_eq!(DynamicAllocation(0).key(), Key::from(*expected_keys[0]));
assert_eq!(DynamicAllocation(1).key(), Key::from(*expected_keys[1]));
}