peridot_native_io/
lib.rs

1use core::mem::MaybeUninit;
2use std::io::{IoSliceMut, Result as IOResult};
3
4mod adapter;
5pub use adapter::*;
6mod buffered;
7pub use buffered::*;
8
9#[cfg(target_os = "android")]
10pub mod android;
11#[cfg(unix)]
12mod generic_unix;
13#[cfg(target_os = "linux")]
14pub mod linux;
15#[cfg(target_os = "macos")]
16pub mod macos;
17#[cfg(windows)]
18pub mod windows;
19
20#[cfg(windows)]
21pub type PlatformNativeFileReader = self::windows::NativeFileBlobRandomReader;
22#[cfg(windows)]
23pub type PlatformNativeFileReaderAsync = self::windows::NativeFileBlobAsyncRandomReader;
24#[cfg(target_os = "linux")]
25pub type PlatformNativeFileReader = self::linux::NativeFileBlobRandomReader;
26#[cfg(target_os = "linux")]
27pub type PlatformNativeFileReaderAsync = self::linux::NativeFileAsyncBlobRandomReader;
28#[cfg(target_os = "android")]
29pub type PlatformNativeFileReader = self::android::BundledAssetRandomReader;
30#[cfg(target_os = "android")]
31pub type PlatformNativeFileReaderAsync = self::android::BundledAssetAsyncRandomReader;
32#[cfg(target_os = "macos")]
33pub type PlatformNativeFileReader = self::macos::NativeFileReader;
34#[cfg(target_os = "macos")]
35pub type PlatformNativeFileReaderAsync = self::macos::NativeFileAsyncReader;
36
37/// Metadata Accessor for an Blob(synchronous).
38pub trait BlobMetadata {
39    fn byte_length(&self) -> std::io::Result<u64>;
40}
41
42/// Metadata Accessor for an Blob(asynchronous).
43pub trait BlobMetadataAsync {
44    fn byte_length_async(&self) -> impl core::future::Future<Output = std::io::Result<u64>>;
45}
46
47/// Read-only random accessible Blob operations(synchronous).
48pub trait RandomReadBlob {
49    fn read(&self, pos: u64, buf: &mut [MaybeUninit<u8>]) -> std::io::Result<usize>;
50
51    #[inline]
52    fn readv(&self, offs: u64, iovecs: &mut [IoSliceMut]) -> std::io::Result<usize> {
53        // default impl for unsupported platforms: read into single iovec
54        match iovecs.first_mut() {
55            None => Ok(0),
56            Some(v) => self.read(offs, unsafe {
57                core::mem::transmute::<&mut [u8], &mut [MaybeUninit<u8>]>(&mut v[..])
58            }),
59        }
60    }
61
62    // utility helpers
63    fn read_exact(&self, offs: u64, buf: &mut [MaybeUninit<u8>]) -> std::io::Result<()> {
64        let mut o = 0;
65        while o < buf.len() {
66            o += self.read(offs + o as u64, &mut buf[o..])?;
67        }
68
69        Ok(())
70    }
71
72    fn readv_all<'a, 'b, 'bb>(
73        &'a self,
74        offs: u64,
75        mut iovecs: &'b mut [IoSliceMut<'bb>],
76    ) -> std::io::Result<()> {
77        // ensure iovecs are actually empty
78        IoSliceMut::advance_slices(&mut iovecs, 0);
79
80        let mut o = 0;
81        while !iovecs.is_empty() {
82            let r = self.readv(offs + o as u64, iovecs)?;
83            IoSliceMut::advance_slices(&mut iovecs, r);
84            o += r;
85        }
86
87        Ok(())
88    }
89
90    fn read_to_end(&self, offs: u64) -> std::io::Result<Vec<u8>> {
91        const GROW_SIZE: usize = 8192;
92
93        let mut buf = Vec::with_capacity(GROW_SIZE);
94        let mut o = 0;
95        loop {
96            let r = match self.read(offs + o as u64, buf.spare_capacity_mut()) {
97                Ok(0) => break,
98                Ok(r) => r,
99                Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => break,
100                Err(e) => return Err(e),
101            };
102
103            o += r;
104            unsafe {
105                buf.set_len(o);
106            }
107            if o >= buf.capacity() {
108                buf.reserve_exact(GROW_SIZE);
109            }
110        }
111
112        buf.shrink_to_fit();
113        Ok(buf)
114    }
115}
116impl<'t, T> RandomReadBlob for &'t T
117where
118    T: RandomReadBlob + ?Sized + 't,
119{
120    #[inline(always)]
121    fn read(&self, pos: u64, buf: &mut [MaybeUninit<u8>]) -> std::io::Result<usize> {
122        T::read(*self, pos, buf)
123    }
124
125    #[inline(always)]
126    fn readv(&self, offs: u64, iovecs: &mut [IoSliceMut]) -> std::io::Result<usize> {
127        T::readv(*self, offs, iovecs)
128    }
129
130    #[inline(always)]
131    fn read_exact(&self, offs: u64, buf: &mut [MaybeUninit<u8>]) -> std::io::Result<()> {
132        T::read_exact(*self, offs, buf)
133    }
134
135    #[inline(always)]
136    fn read_to_end(&self, offs: u64) -> std::io::Result<Vec<u8>> {
137        T::read_to_end(*self, offs)
138    }
139
140    #[inline(always)]
141    fn readv_all<'a, 'b, 'bb>(
142        &'a self,
143        offs: u64,
144        iovecs: &'b mut [IoSliceMut<'bb>],
145    ) -> std::io::Result<()> {
146        T::readv_all(*self, offs, iovecs)
147    }
148}
149
150/// Read-only random accessible Blob operations(asynchronous).
151pub trait RandomReadBlobAsync {
152    type ReadFuture<'a, 'b>: Future<Output = std::io::Result<usize>>
153    where
154        Self: 'a;
155    type ReadVecFuture<'a, 'b, 'bb>: Future<Output = std::io::Result<usize>>
156    where
157        Self: 'a,
158        'bb: 'b;
159
160    fn read_async<'a, 'b>(
161        &'a self,
162        offs: u64,
163        buf: &'b mut [MaybeUninit<u8>],
164    ) -> Self::ReadFuture<'a, 'b>;
165    fn readv_async<'a, 'b, 'bb>(
166        &'a self,
167        offs: u64,
168        iovecs: &'b mut [IoSliceMut<'bb>],
169    ) -> Self::ReadVecFuture<'a, 'b, 'bb>;
170
171    // utility helpers
172    fn read_exact_async<'a, 'b>(
173        &'a self,
174        offs: u64,
175        buf: &'b mut [MaybeUninit<u8>],
176    ) -> impl core::future::Future<Output = IOResult<()>> + use<'a, 'b, Self> {
177        async move {
178            let mut o = 0;
179            while o < buf.len() {
180                let r = self.read_async(offs + o as u64, &mut buf[o..]).await?;
181                o += r;
182            }
183
184            Ok(())
185        }
186    }
187
188    fn readv_all_async<'a, 'b, 'bb>(
189        &'a self,
190        offs: u64,
191        mut iovecs: &'b mut [IoSliceMut<'bb>],
192    ) -> impl core::future::Future<Output = std::io::Result<()>> + use<'a, 'b, 'bb, Self> {
193        async move {
194            // ensure iovecs are actually empty
195            IoSliceMut::advance_slices(&mut iovecs, 0);
196
197            let mut o = 0;
198            while !iovecs.is_empty() {
199                let r = self.readv_async(offs + o as u64, iovecs).await?;
200                IoSliceMut::advance_slices(&mut iovecs, r);
201                o += r;
202            }
203
204            Ok(())
205        }
206    }
207
208    fn read_to_end_async<'a>(
209        &'a self,
210        offs: u64,
211    ) -> impl core::future::Future<Output = IOResult<Vec<u8>>> + use<'a, Self> {
212        async move {
213            const GROW_SIZE: usize = 8192;
214
215            let mut buf = Vec::with_capacity(GROW_SIZE);
216            let mut o = 0;
217            loop {
218                let r = match self
219                    .read_async(offs + o as u64, buf.spare_capacity_mut())
220                    .await
221                {
222                    Ok(0) => break,
223                    Ok(r) => r,
224                    Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => break,
225                    Err(e) => return Err(e),
226                };
227
228                o += r;
229                unsafe {
230                    buf.set_len(o);
231                }
232                if o >= buf.capacity() {
233                    buf.reserve_exact(GROW_SIZE);
234                }
235            }
236
237            buf.shrink_to_fit();
238            Ok(buf)
239        }
240    }
241}
242impl<'t, T> RandomReadBlobAsync for &'t T
243where
244    T: RandomReadBlobAsync + ?Sized + 't,
245{
246    type ReadFuture<'a, 'b>
247        = T::ReadFuture<'a, 'b>
248    where
249        Self: 'a;
250    type ReadVecFuture<'a, 'b, 'bb>
251        = T::ReadVecFuture<'a, 'b, 'bb>
252    where
253        Self: 'a,
254        'bb: 'b;
255
256    #[inline(always)]
257    fn read_async<'a, 'b>(
258        &'a self,
259        offs: u64,
260        buf: &'b mut [MaybeUninit<u8>],
261    ) -> Self::ReadFuture<'a, 'b> {
262        T::read_async(*self, offs, buf)
263    }
264
265    #[inline(always)]
266    fn readv_async<'a, 'b, 'bb>(
267        &'a self,
268        offs: u64,
269        iovecs: &'b mut [IoSliceMut<'bb>],
270    ) -> Self::ReadVecFuture<'a, 'b, 'bb> {
271        T::readv_async(*self, offs, iovecs)
272    }
273
274    #[inline(always)]
275    fn read_exact_async<'a, 'b>(
276        &'a self,
277        offs: u64,
278        buf: &'b mut [MaybeUninit<u8>],
279    ) -> impl core::future::Future<Output = IOResult<()>> + use<'a, 'b, 't, T> {
280        T::read_exact_async(*self, offs, buf)
281    }
282
283    #[inline(always)]
284    fn read_to_end_async<'a>(
285        &'a self,
286        offs: u64,
287    ) -> impl core::future::Future<Output = IOResult<Vec<u8>>> + use<'a, 't, T> {
288        T::read_to_end_async(*self, offs)
289    }
290
291    #[inline(always)]
292    fn readv_all_async<'a, 'b, 'bb>(
293        &'a self,
294        offs: u64,
295        iovecs: &'b mut [IoSliceMut<'bb>],
296    ) -> impl core::future::Future<Output = std::io::Result<()>> + use<'a, 'b, 'bb, 't, T> {
297        T::readv_all_async(*self, offs, iovecs)
298    }
299}
300
301/// An Blob object that can be mapped into a memory.
302pub trait MemoryMapBlob {
303    type MemoryUnmapData;
304
305    fn mmap(
306        &self,
307        offs: u64,
308        len: usize,
309    ) -> std::io::Result<(*mut core::ffi::c_void, Self::MemoryUnmapData)>;
310    fn munmap(&self, data: Self::MemoryUnmapData) -> std::io::Result<()>;
311}
312impl<'t, T> MemoryMapBlob for &'t T
313where
314    T: MemoryMapBlob + ?Sized + 't,
315{
316    type MemoryUnmapData = T::MemoryUnmapData;
317
318    #[inline(always)]
319    fn mmap(
320        &self,
321        offs: u64,
322        len: usize,
323    ) -> std::io::Result<(*mut core::ffi::c_void, Self::MemoryUnmapData)> {
324        T::mmap(*self, offs, len)
325    }
326
327    #[inline(always)]
328    fn munmap(&self, data: Self::MemoryUnmapData) -> std::io::Result<()> {
329        T::munmap(*self, data)
330    }
331}