nectar_primitives/file/
mod.rs1mod constants;
46pub mod entry_ref;
47pub mod error;
48mod frontier;
49mod helpers;
50#[cfg(test)]
51#[macro_use]
52mod joiner_tests;
53#[cfg(test)]
54#[macro_use]
55mod splitter_tests;
56mod joiner;
57pub mod mode;
58mod sync_joiner;
59mod sync_read_at;
60mod sync_splitter;
61mod sync_splitter_parallel;
62mod tree;
63
64use crate::chunk::ChunkAddress;
65#[cfg(feature = "encryption")]
66use crate::chunk::encryption::EncryptedChunkRef;
67use crate::store::{SyncChunkGet, SyncChunkPut};
68
69#[cfg(feature = "encryption")]
71pub use joiner::EncryptedJoiner;
72#[cfg(feature = "tokio")]
73pub use joiner::JoinerReader;
74pub use joiner::{GenericJoiner, Joiner};
75#[cfg(feature = "encryption")]
77pub use sync_joiner::EncryptedSyncJoiner;
78pub use sync_joiner::{GenericSyncJoiner, SyncJoiner};
79pub use sync_read_at::SyncReadAt;
80#[cfg(feature = "encryption")]
81pub use sync_splitter::EncryptedSyncSplitter;
82pub use sync_splitter::SyncSplitter;
83#[cfg(feature = "encryption")]
84pub use sync_splitter_parallel::EncryptedSyncParallelSplitter;
85pub use sync_splitter_parallel::SyncParallelSplitter;
86
87pub use entry_ref::EntryRef;
88pub use error::FileError;
89pub use tree::{ChunkRange, TreeParams};
90
91mod join_ref_sealed {
92 pub trait Sealed {}
93 impl Sealed for crate::ChunkAddress {}
94 #[cfg(feature = "encryption")]
95 impl Sealed for crate::EncryptedChunkRef {}
96}
97
98pub trait JoinRef: join_ref_sealed::Sealed + Clone + Send + Sync + 'static {
101 type Mode: mode::JoinMode + Send + Sync;
103
104 fn into_root_ref(self) -> <Self::Mode as mode::JoinMode>::RootRef;
106}
107
108impl JoinRef for ChunkAddress {
109 type Mode = mode::PlainMode;
110
111 fn into_root_ref(self) -> Self {
112 self
113 }
114}
115
116#[cfg(feature = "encryption")]
117impl JoinRef for EncryptedChunkRef {
118 type Mode = mode::EncryptedMode;
119
120 fn into_root_ref(self) -> Self {
121 self
122 }
123}
124
125pub(crate) fn resolve_seek_position(
127 pos: std::io::SeekFrom,
128 current: u64,
129 span: u64,
130) -> std::io::Result<u64> {
131 use std::io::{Error, ErrorKind::InvalidInput, SeekFrom};
132 let to_i64 = |v: u64, msg: &str| i64::try_from(v).map_err(|_| Error::new(InvalidInput, msg));
133 let new_pos = match pos {
134 SeekFrom::Start(off) => to_i64(off, "seek offset exceeds i64::MAX")?,
135 SeekFrom::End(off) => to_i64(span, "file span exceeds i64::MAX")? + off,
136 SeekFrom::Current(off) => to_i64(current, "current position exceeds i64::MAX")? + off,
137 };
138 if new_pos < 0 {
139 return Err(Error::new(InvalidInput, "seek to negative position"));
140 }
141 Ok(new_pos as u64)
142}
143
144pub async fn join<R, G, const BODY_SIZE: usize>(getter: G, root: R) -> error::Result<Vec<u8>>
148where
149 R: JoinRef,
150 G: crate::store::ChunkGet<BODY_SIZE>,
151{
152 GenericJoiner::<G, R::Mode, BODY_SIZE>::new(getter, root.into_root_ref())
153 .await?
154 .read_all()
155 .await
156}
157
158pub fn sync_split<const BODY_SIZE: usize>(
164 data: &[u8],
165) -> error::Result<(ChunkAddress, crate::store::MemoryStore<BODY_SIZE>)> {
166 let store = crate::store::MemoryStore::<BODY_SIZE>::new();
167 let splitter = SyncParallelSplitter::new(store);
168 let root = splitter.split(&data)?;
169 Ok((root, splitter.into_store()))
170}
171
172#[cfg(feature = "encryption")]
174pub fn sync_split_encrypted<const BODY_SIZE: usize>(
175 data: &[u8],
176) -> error::Result<(EncryptedChunkRef, crate::store::MemoryStore<BODY_SIZE>)> {
177 let store = crate::store::MemoryStore::<BODY_SIZE>::new();
178 let splitter = EncryptedSyncParallelSplitter::new(store);
179 let root_ref = splitter.split(&data)?;
180 Ok((root_ref, splitter.into_store()))
181}
182
183pub fn sync_join<R, G, const BODY_SIZE: usize>(getter: G, root: R) -> error::Result<Vec<u8>>
185where
186 R: JoinRef,
187 G: SyncChunkGet<BODY_SIZE> + Clone + Send + Sync,
188{
189 GenericSyncJoiner::<G, R::Mode, BODY_SIZE>::new(getter, root.into_root_ref())?.read_all()
190}
191
192#[cfg(test)]
194pub(crate) const fn levels(length: u64, chunk_size: usize) -> usize {
195 constants::tree_depth(length, chunk_size, constants::REF_SIZE)
196}
197
198pub trait ChunkGetExt<const BODY_SIZE: usize>: crate::store::ChunkGet<BODY_SIZE> {
204 fn joiner<R: JoinRef>(
206 self,
207 root: R,
208 ) -> impl std::future::Future<Output = error::Result<GenericJoiner<Self, R::Mode, BODY_SIZE>>> + Send
209 where
210 Self: Sized + Clone + Send + Sync + 'static,
211 {
212 GenericJoiner::new(self, root.into_root_ref())
213 }
214
215 fn read_file<R: JoinRef>(
217 self,
218 root: R,
219 ) -> impl std::future::Future<Output = error::Result<Vec<u8>>> + Send
220 where
221 Self: Sized + Clone + Send + Sync + 'static,
222 {
223 join(self, root)
224 }
225}
226
227impl<T, const BODY_SIZE: usize> ChunkGetExt<BODY_SIZE> for T where
228 T: crate::store::ChunkGet<BODY_SIZE>
229{
230}
231
232pub trait SyncChunkGetExt<const BODY_SIZE: usize>: SyncChunkGet<BODY_SIZE> {
248 fn joiner<R: JoinRef>(
250 self,
251 root: R,
252 ) -> error::Result<GenericSyncJoiner<Self, R::Mode, BODY_SIZE>>
253 where
254 Self: Clone + Send + Sync + Sized,
255 {
256 GenericSyncJoiner::new(self, root.into_root_ref())
257 }
258
259 fn read_file<R: JoinRef>(self, root: R) -> error::Result<Vec<u8>>
261 where
262 Self: Clone + Send + Sync + Sized,
263 {
264 sync_join(self, root)
265 }
266}
267
268impl<T, const BODY_SIZE: usize> SyncChunkGetExt<BODY_SIZE> for T where T: SyncChunkGet<BODY_SIZE> {}
269
270pub trait SyncChunkPutExt<const BODY_SIZE: usize>: SyncChunkPut<BODY_SIZE> {
290 fn writer(&self, size: u64) -> SyncSplitter<&Self, BODY_SIZE>
293 where
294 Self: Sized,
295 {
296 SyncSplitter::new(self, size)
297 }
298
299 #[cfg(feature = "encryption")]
301 fn encrypted_writer(&self, size: u64) -> EncryptedSyncSplitter<&Self, BODY_SIZE>
302 where
303 Self: Sized,
304 {
305 EncryptedSyncSplitter::new(self, size)
306 }
307
308 fn write_file(&self, data: &[u8]) -> error::Result<ChunkAddress>
310 where
311 Self: Send + Sync + Sized,
312 {
313 SyncParallelSplitter::<&Self, BODY_SIZE>::new(self).split(&data)
314 }
315
316 #[cfg(feature = "encryption")]
318 fn write_encrypted_file(&self, data: &[u8]) -> error::Result<EncryptedChunkRef>
319 where
320 Self: Send + Sync + Sized,
321 {
322 EncryptedSyncParallelSplitter::<&Self, BODY_SIZE>::new(self).split(&data)
323 }
324}
325
326impl<T, const BODY_SIZE: usize> SyncChunkPutExt<BODY_SIZE> for T where T: SyncChunkPut<BODY_SIZE> {}
327
328#[cfg(test)]
329mod tests;