Skip to main content

midnight_base_crypto/
repr.rs

1// This file is part of midnight-ledger.
2// Copyright (C) 2025 Midnight Foundation
3// SPDX-License-Identifier: Apache-2.0
4// Licensed under the Apache License, Version 2.0 (the "License");
5// You may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7// http://www.apache.org/licenses/LICENSE-2.0
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14//! This module deals with representing data as sequences of binary objects for
15//! use in persistent hashing.
16
17pub use derive::BinaryHashRepr;
18use serialize::VecExt;
19use std::io;
20
21/// Something that can be written to from in-memory buffers
22pub trait MemWrite<T> {
23    /// Write a buffer into memory.
24    fn write(&mut self, buf: &[T]);
25}
26
27impl<T: Copy> MemWrite<T> for Vec<T> {
28    fn write(&mut self, buf: &[T]) {
29        self.extend(buf);
30    }
31}
32
33impl<T, W: MemWrite<T>> MemWrite<T> for &mut W {
34    fn write(&mut self, buf: &[T]) {
35        W::write(self, buf);
36    }
37}
38
39/// TODO: describe
40pub struct IoWrite<W: MemWrite<u8>>(pub W);
41
42impl<W: MemWrite<u8>> io::Write for IoWrite<W> {
43    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
44        self.0.write(buf);
45        Ok(buf.len())
46    }
47    fn flush(&mut self) -> io::Result<()> {
48        Ok(())
49    }
50}
51
52/// An object that can be represented as a sequence of hash-able chunks.
53pub trait BinaryHashRepr {
54    /// Writes out the binary representation of this value into a writer.
55    fn binary_repr<W: MemWrite<u8>>(&self, writer: &mut W);
56    /// The size of an object's binary representation.
57    fn binary_len(&self) -> usize;
58    /// Writes the hash repr into a vector
59    fn binary_vec(&self) -> Vec<u8> {
60        let mut res = Vec::with_bounded_capacity(self.binary_len());
61        self.binary_repr(&mut res);
62        res
63    }
64}
65
66impl BinaryHashRepr for [u8] {
67    fn binary_repr<W: MemWrite<u8>>(&self, writer: &mut W) {
68        writer.write(self);
69    }
70    fn binary_len(&self) -> usize {
71        self.len()
72    }
73}
74
75impl<const N: usize> BinaryHashRepr for [u8; N] {
76    fn binary_repr<W: MemWrite<u8>>(&self, writer: &mut W) {
77        writer.write(self)
78    }
79    fn binary_len(&self) -> usize {
80        N
81    }
82}
83
84macro_rules! integer_hash_repr {
85    ($($ty:ty),*) => {
86        $(
87            impl BinaryHashRepr for $ty {
88                fn binary_repr<W: MemWrite<u8>>(&self, writer: &mut W) {
89                    writer.write(&self.to_le_bytes());
90                }
91                fn binary_len(&self) -> usize {
92                    <$ty>::BITS as usize / 8
93                }
94            }
95        )*
96    }
97}
98
99macro_rules! tuple_repr {
100    ($head:ident$(, $tail:ident)*) => {
101        #[allow(unused_parens, non_snake_case)]
102        impl<$head: BinaryHashRepr$(, $tail: BinaryHashRepr)*> BinaryHashRepr for ($head, $($tail),*) {
103            fn binary_repr<W: MemWrite<u8>>(&self, writer: &mut W) {
104                let ($head, $($tail),*) = self;
105                $head.binary_repr(writer);
106                $($tail.binary_repr(writer);)*
107            }
108            fn binary_len(&self) -> usize {
109                let ($head, $($tail),*) = self;
110                $head.binary_len() $(+ $tail.binary_len())*
111            }
112        }
113        tuple_repr!($($tail),*);
114    };
115    () => {
116        impl BinaryHashRepr for () {
117            fn binary_repr<W: MemWrite<u8>>(&self, _: &mut W) {
118            }
119            fn binary_len(&self) -> usize {
120                0
121            }
122        }
123    };
124}
125
126tuple_repr!(A, B, C, D, E, F, G, H, I, J, K, L);
127
128integer_hash_repr!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128);
129
130impl BinaryHashRepr for bool {
131    fn binary_repr<W: MemWrite<u8>>(&self, writer: &mut W) {
132        writer.write(&[*self as u8]);
133    }
134    fn binary_len(&self) -> usize {
135        1
136    }
137}