zebra_state/service/finalized_state/
disk_format.rs1use std::sync::Arc;
9
10pub mod block;
11pub mod chain;
12pub mod shielded;
13pub mod transparent;
14pub mod upgrade;
15
16#[cfg(any(test, feature = "proptest-impl"))]
17mod tests;
18
19pub use block::{TransactionIndex, TransactionLocation, MAX_ON_DISK_HEIGHT};
20pub use transparent::OutputLocation;
21
22#[cfg(any(test, feature = "proptest-impl"))]
23pub use tests::KV;
24
25pub trait IntoDisk {
28 type Bytes: AsRef<[u8]>;
31
32 fn as_bytes(&self) -> Self::Bytes;
44}
45
46pub trait FromDisk: Sized {
48 fn from_bytes(bytes: impl AsRef<[u8]>) -> Self;
58}
59
60impl<T> IntoDisk for &T
63where
64 T: IntoDisk,
65{
66 type Bytes = T::Bytes;
67
68 fn as_bytes(&self) -> Self::Bytes {
69 T::as_bytes(*self)
70 }
71}
72
73impl<T> IntoDisk for Arc<T>
74where
75 T: IntoDisk,
76{
77 type Bytes = T::Bytes;
78
79 fn as_bytes(&self) -> Self::Bytes {
80 T::as_bytes(self)
81 }
82}
83
84impl<T> FromDisk for Arc<T>
85where
86 T: FromDisk,
87{
88 fn from_bytes(bytes: impl AsRef<[u8]>) -> Self {
89 Arc::new(T::from_bytes(bytes))
90 }
91}
92
93impl IntoDisk for () {
96 type Bytes = [u8; 0];
97
98 fn as_bytes(&self) -> Self::Bytes {
99 []
100 }
101}
102
103impl FromDisk for () {
104 #[allow(clippy::unused_unit)]
105 fn from_bytes(bytes: impl AsRef<[u8]>) -> Self {
106 assert_eq!(
107 bytes.as_ref().len(),
108 0,
109 "unexpected data in zero-sized column family type",
110 );
111
112 ()
113 }
114}
115
116#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
119pub struct RawBytes(Vec<u8>);
120
121impl RawBytes {
125 pub fn new_raw_bytes(bytes: Vec<u8>) -> Self {
130 Self(bytes)
131 }
132
133 pub fn raw_bytes(&self) -> &Vec<u8> {
136 &self.0
137 }
138}
139
140impl IntoDisk for RawBytes {
141 type Bytes = Vec<u8>;
142
143 fn as_bytes(&self) -> Self::Bytes {
144 self.raw_bytes().clone()
145 }
146}
147
148impl FromDisk for RawBytes {
149 fn from_bytes(bytes: impl AsRef<[u8]>) -> Self {
150 Self::new_raw_bytes(bytes.as_ref().to_vec())
151 }
152}
153
154pub fn truncate_zero_be_bytes(mem_bytes: &[u8], disk_len: usize) -> Option<&[u8]> {
165 let discarded_bytes = mem_bytes
166 .len()
167 .checked_sub(disk_len)
168 .expect("unexpected `mem_bytes` length: must be at least `disk_len`");
169
170 if discarded_bytes == 0 {
171 return Some(mem_bytes);
172 }
173
174 let (discarded, truncated) = mem_bytes.split_at(discarded_bytes);
175
176 if !discarded.iter().all(|&byte| byte == 0) {
177 return None;
178 }
179
180 assert_eq!(truncated.len(), disk_len);
181
182 Some(truncated)
183}
184
185pub fn expand_zero_be_bytes(disk_bytes: &[u8], mem_len: usize) -> Vec<u8> {
192 let extra_bytes = mem_len
193 .checked_sub(disk_bytes.len())
194 .expect("unexpected `disk_bytes` length: must not exceed `mem_len`");
195
196 if extra_bytes == 0 {
197 return disk_bytes.to_vec();
198 }
199
200 let mut expanded = vec![0; extra_bytes];
201 expanded.extend(disk_bytes);
202
203 assert_eq!(expanded.len(), mem_len);
204
205 expanded
206}