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(feature = "shielded-scan")]
17pub mod scan;
18
19#[cfg(any(test, feature = "proptest-impl"))]
20mod tests;
21
22pub use block::{TransactionIndex, TransactionLocation, MAX_ON_DISK_HEIGHT};
23pub use transparent::{OutputIndex, OutputLocation};
24
25#[cfg(feature = "shielded-scan")]
26pub use scan::{
27 SaplingScannedDatabaseEntry, SaplingScannedDatabaseIndex, SaplingScannedResult,
28 SaplingScanningKey,
29};
30
31#[cfg(any(test, feature = "proptest-impl"))]
32pub use tests::KV;
33
34pub trait IntoDisk {
37 type Bytes: AsRef<[u8]>;
40
41 fn as_bytes(&self) -> Self::Bytes;
53}
54
55pub trait FromDisk: Sized {
57 fn from_bytes(bytes: impl AsRef<[u8]>) -> Self;
67}
68
69impl<T> IntoDisk for &T
72where
73 T: IntoDisk,
74{
75 type Bytes = T::Bytes;
76
77 fn as_bytes(&self) -> Self::Bytes {
78 T::as_bytes(*self)
79 }
80}
81
82impl<T> IntoDisk for Arc<T>
83where
84 T: IntoDisk,
85{
86 type Bytes = T::Bytes;
87
88 fn as_bytes(&self) -> Self::Bytes {
89 T::as_bytes(self)
90 }
91}
92
93impl<T> FromDisk for Arc<T>
94where
95 T: FromDisk,
96{
97 fn from_bytes(bytes: impl AsRef<[u8]>) -> Self {
98 Arc::new(T::from_bytes(bytes))
99 }
100}
101
102impl IntoDisk for () {
105 type Bytes = [u8; 0];
106
107 fn as_bytes(&self) -> Self::Bytes {
108 []
109 }
110}
111
112impl FromDisk for () {
113 #[allow(clippy::unused_unit)]
114 fn from_bytes(bytes: impl AsRef<[u8]>) -> Self {
115 assert_eq!(
116 bytes.as_ref().len(),
117 0,
118 "unexpected data in zero-sized column family type",
119 );
120
121 ()
122 }
123}
124
125#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
128pub struct RawBytes(Vec<u8>);
129
130impl RawBytes {
134 pub fn new_raw_bytes(bytes: Vec<u8>) -> Self {
139 Self(bytes)
140 }
141
142 pub fn raw_bytes(&self) -> &Vec<u8> {
145 &self.0
146 }
147}
148
149impl IntoDisk for RawBytes {
150 type Bytes = Vec<u8>;
151
152 fn as_bytes(&self) -> Self::Bytes {
153 self.raw_bytes().clone()
154 }
155}
156
157impl FromDisk for RawBytes {
158 fn from_bytes(bytes: impl AsRef<[u8]>) -> Self {
159 Self::new_raw_bytes(bytes.as_ref().to_vec())
160 }
161}
162
163pub fn truncate_zero_be_bytes(mem_bytes: &[u8], disk_len: usize) -> Option<&[u8]> {
174 let discarded_bytes = mem_bytes
175 .len()
176 .checked_sub(disk_len)
177 .expect("unexpected `mem_bytes` length: must be at least `disk_len`");
178
179 if discarded_bytes == 0 {
180 return Some(mem_bytes);
181 }
182
183 let (discarded, truncated) = mem_bytes.split_at(discarded_bytes);
184
185 if !discarded.iter().all(|&byte| byte == 0) {
186 return None;
187 }
188
189 assert_eq!(truncated.len(), disk_len);
190
191 Some(truncated)
192}
193
194pub fn expand_zero_be_bytes(disk_bytes: &[u8], mem_len: usize) -> Vec<u8> {
201 let extra_bytes = mem_len
202 .checked_sub(disk_bytes.len())
203 .expect("unexpected `disk_bytes` length: must not exceed `mem_len`");
204
205 if extra_bytes == 0 {
206 return disk_bytes.to_vec();
207 }
208
209 let mut expanded = vec![0; extra_bytes];
210 expanded.extend(disk_bytes);
211
212 assert_eq!(expanded.len(), mem_len);
213
214 expanded
215}