io_arrays/
arrays.rs

1use crate::{filelike, Advice};
2#[cfg(not(any(target_os = "android", target_os = "linux")))]
3use io_lifetimes::OwnedFilelike;
4#[cfg(not(windows))]
5use io_lifetimes::{AsFd, BorrowedFd};
6use io_lifetimes::{FromFilelike, IntoFilelike};
7#[cfg(feature = "io-streams")]
8use io_streams::StreamReader;
9use std::fs;
10use std::io::{self, IoSlice, IoSliceMut, Read, Seek, Write};
11#[cfg(unix)]
12use std::os::unix::io::{AsRawFd, RawFd};
13#[cfg(target_os = "wasi")]
14use std::os::wasi::io::{AsRawFd, RawFd};
15/*
16use system_interface::fs::FileIoExt;
17*/
18#[cfg(windows)]
19use {
20    io_extras::os::windows::{AsRawHandleOrSocket, RawHandleOrSocket},
21    io_lifetimes::{AsHandle, BorrowedHandle},
22    std::os::windows::io::{AsRawHandle, RawHandle},
23};
24
25/// Metadata information about an array.
26///
27/// This is somewhat analogous to [`std::fs::Metadata`], however it only
28/// includes a few fields, since arrays are more abstract than files.
29pub struct Metadata {
30    pub(crate) len: u64,
31    pub(crate) blksize: u64,
32}
33
34#[allow(clippy::len_without_is_empty)]
35impl Metadata {
36    /// Returns the size of the array, in bytes, this metadata is for.
37    #[inline]
38    #[must_use]
39    pub const fn len(&self) -> u64 {
40        self.len
41    }
42
43    /// Returns the block size for I/O.
44    #[inline]
45    #[must_use]
46    pub const fn blksize(&self) -> u64 {
47        self.blksize
48    }
49}
50
51/// A minimal base trait for array I/O. Defines operations common to all kinds
52/// of random-access devices that fit the "array" concept, including normal
53/// files, block devices, and in-memory buffers.
54///
55/// This is a base trait that [`ReadAt`], [`WriteAt`], and [`EditAt`] all
56/// share.
57pub trait Array {
58    /// Return the [`Metadata`] for the array. This is similar to
59    /// [`std::fs::File::metadata`], though it returns fewer fields since the
60    /// underlying device may not be an actual filesystem inode.
61    fn metadata(&self) -> io::Result<Metadata>;
62
63    /// Announce the expected access pattern of the data at the given offset.
64    ///
65    /// This is purely a performance hint and has no semantic effect.
66    fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()>;
67}
68
69/// A trait for reading from arrays.
70///
71/// This is similar to [`std::io::Read`] except all of the reading functions
72/// take an `offset` parameter, specifying a position in the array to read at.
73///
74/// Unlike `std::io::Read`, `ReadAt`'s functions take a `&self` rather than a
75/// `&mut self`, since they don't have a current position to mutate.
76pub trait ReadAt: Array {
77    /// Reads a number of bytes starting from a given offset.
78    ///
79    /// This is similar to [`std::os::unix::fs::FileExt::read_at`], except it
80    /// takes `self` by immutable reference since the entire side effect is
81    /// I/O, and it's supported on non-Unix platforms including Windows.
82    ///
83    /// [`std::os::unix::fs::FileExt::read_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#tymethod.read_at
84    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
85
86    /// Reads the exact number of byte required to fill `buf` from the given
87    /// offset.
88    ///
89    /// This is similar to [`std::os::unix::fs::FileExt::read_exact_at`],
90    /// except it takes `self` by immutable reference since the entire side
91    /// effect is I/O, and it's supported on non-Unix platforms including
92    /// Windows.
93    ///
94    /// [`std::os::unix::fs::FileExt::read_exact_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#tymethod.read_exact_at
95    fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()>;
96
97    /// Is to `read_vectored` what `read_at` is to `read`.
98    fn read_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result<usize>;
99
100    /// Is to `read_exact_vectored` what `read_exact_at` is to `read_exact`.
101    fn read_exact_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result<()>;
102
103    /// Determines if `Self` has an efficient `read_vectored_at`
104    /// implementation.
105    fn is_read_vectored_at(&self) -> bool;
106
107    /// Create a `StreamReader` which reads from the array at the given offset.
108    #[cfg(feature = "io-streams")]
109    fn read_via_stream_at(&self, offset: u64) -> io::Result<StreamReader>;
110}
111
112/// A trait for writing to arrays.
113///
114/// This is similar to [`std::io::Write`] except all of the reading functions
115/// take an `offset` parameter, specifying a position in the array to read at.
116pub trait WriteAt: Array {
117    /// Writes a number of bytes starting from a given offset.
118    ///
119    /// This is similar to [`std::os::unix::fs::FileExt::write_at`], except it
120    /// takes `self` by immutable reference since the entire side effect is
121    /// I/O, and it's supported on non-Unix platforms including Windows.
122    ///
123    /// [`std::os::unix::fs::FileExt::write_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#tymethod.write_at
124    fn write_at(&mut self, buf: &[u8], offset: u64) -> io::Result<usize>;
125
126    /// Attempts to write an entire buffer starting from a given offset.
127    ///
128    /// This is similar to [`std::os::unix::fs::FileExt::write_all_at`], except
129    /// it takes `self` by immutable reference since the entire side effect is
130    /// I/O, and it's supported on non-Unix platforms including Windows.
131    ///
132    /// [`std::os::unix::fs::FileExt::write_all_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#tymethod.write_all_at
133    fn write_all_at(&mut self, buf: &[u8], offset: u64) -> io::Result<()>;
134
135    /// Is to `write_vectored` what `write_at` is to `write`.
136    fn write_vectored_at(&mut self, bufs: &[IoSlice], offset: u64) -> io::Result<usize>;
137
138    /// Is to `write_all_vectored` what `write_all_at` is to `write_all`.
139    fn write_all_vectored_at(&mut self, bufs: &mut [IoSlice], offset: u64) -> io::Result<()>;
140
141    /// Determines if `Self` has an efficient `write_vectored_at`
142    /// implementation.
143    fn is_write_vectored_at(&self) -> bool;
144
145    /// Copy `len` bytes from `input` at `input_offset` to `self` at `offset`.
146    fn copy_from<R: ReadAt>(
147        &mut self,
148        offset: u64,
149        input: &R,
150        input_offset: u64,
151        len: u64,
152    ) -> io::Result<u64>;
153
154    /// Truncates or extends the underlying array, updating the size of this
155    /// array to become `size`.
156    fn set_len(&mut self, size: u64) -> io::Result<()>;
157}
158
159/// A trait for reading and writing to arrays.
160///
161/// This trait simply combines [`ReadAt`] and [`WriteAt`] and has a blanket
162/// implementation for any type that implements both.
163pub trait EditAt: ReadAt + WriteAt {}
164
165impl<T: ReadAt + WriteAt> EditAt for T {}
166
167/// A random-access input source.
168#[derive(Debug)]
169pub struct ArrayReader {
170    file: fs::File,
171}
172
173/// A random-access output sink.
174#[derive(Debug)]
175pub struct ArrayWriter {
176    file: fs::File,
177}
178
179/// A random-access input source and output sink.
180#[derive(Debug)]
181pub struct ArrayEditor {
182    file: fs::File,
183}
184
185impl ArrayReader {
186    /// Convert a `File` into a `ArrayReader`.
187    #[inline]
188    #[must_use]
189    pub fn file<Filelike: IntoFilelike + Read + Seek>(filelike: Filelike) -> Self {
190        Self {
191            file: fs::File::from_into_filelike(filelike),
192        }
193    }
194
195    /// Copy a slice of bytes into a memory buffer to allow it to be accessed
196    /// in the manner of an array.
197    #[inline]
198    pub fn bytes(bytes: &[u8]) -> io::Result<Self> {
199        let owned = create_anonymous()?;
200        let mut file = fs::File::from_into_filelike(owned);
201        file.write_all(bytes)?;
202        Ok(Self { file })
203    }
204}
205
206impl ArrayWriter {
207    /// Convert a `File` into a `ArrayWriter`.
208    ///
209    /// The file must not be opened in [append mode].
210    ///
211    /// [append mode]: https://doc.rust-lang.org/stable/std/fs/struct.OpenOptions.html#method.append
212    #[inline]
213    #[must_use]
214    pub fn file<Filelike: IntoFilelike + Write + Seek>(filelike: Filelike) -> Self {
215        Self::_file(fs::File::from_into_filelike(filelike))
216    }
217
218    #[inline]
219    fn _file(file: fs::File) -> Self {
220        // On Linux, `pwrite` on a file opened with `O_APPEND` writes to the
221        // end of the file, ignoring the offset.
222        #[cfg(not(windows))]
223        {
224            assert!(
225                !rustix::fs::fcntl_getfl(&file)
226                    .unwrap()
227                    .contains(rustix::fs::OFlags::APPEND),
228                "ArrayWriter doesn't support files opened with O_APPEND"
229            );
230        }
231        #[cfg(windows)]
232        {
233            assert!(
234                (winx::file::query_access_information(file.as_handle()).unwrap()
235                    & winx::file::AccessMode::FILE_APPEND_DATA)
236                    == winx::file::AccessMode::FILE_APPEND_DATA,
237                "ArrayWriter doesn't support files opened with FILE_APPEND_DATA"
238            );
239        }
240
241        Self { file }
242    }
243}
244
245impl ArrayEditor {
246    /// Convert a `File` into a `ArrayEditor`.
247    #[inline]
248    #[must_use]
249    pub fn file<Filelike: IntoFilelike + Read + Write + Seek>(filelike: Filelike) -> Self {
250        Self {
251            file: fs::File::from_into_filelike(filelike),
252        }
253    }
254
255    /// Create a temporary anonymous resource which can be accessed in the
256    /// manner of an array.
257    #[inline]
258    pub fn anonymous() -> io::Result<Self> {
259        let owned = create_anonymous()?;
260        Ok(Self {
261            file: fs::File::from_into_filelike(owned),
262        })
263    }
264}
265
266impl Array for ArrayReader {
267    #[inline]
268    fn metadata(&self) -> io::Result<Metadata> {
269        filelike::metadata(self)
270    }
271
272    #[inline]
273    fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
274        filelike::advise(self, offset, len, advice)
275    }
276}
277
278impl Array for &ArrayReader {
279    #[inline]
280    fn metadata(&self) -> io::Result<Metadata> {
281        filelike::metadata(self)
282    }
283
284    #[inline]
285    fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
286        filelike::advise(self, offset, len, advice)
287    }
288}
289
290impl Array for ArrayWriter {
291    #[inline]
292    fn metadata(&self) -> io::Result<Metadata> {
293        filelike::metadata(self)
294    }
295
296    #[inline]
297    fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
298        filelike::advise(self, offset, len, advice)
299    }
300}
301
302impl Array for &ArrayWriter {
303    #[inline]
304    fn metadata(&self) -> io::Result<Metadata> {
305        filelike::metadata(self)
306    }
307
308    #[inline]
309    fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
310        filelike::advise(self, offset, len, advice)
311    }
312}
313
314impl Array for ArrayEditor {
315    #[inline]
316    fn metadata(&self) -> io::Result<Metadata> {
317        filelike::metadata(self)
318    }
319
320    #[inline]
321    fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
322        filelike::advise(self, offset, len, advice)
323    }
324}
325
326impl Array for &ArrayEditor {
327    #[inline]
328    fn metadata(&self) -> io::Result<Metadata> {
329        filelike::metadata(self)
330    }
331
332    #[inline]
333    fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
334        filelike::advise(self, offset, len, advice)
335    }
336}
337
338impl ReadAt for ArrayReader {
339    #[inline]
340    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
341        filelike::read_at(self, buf, offset)
342    }
343
344    #[inline]
345    fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
346        filelike::read_exact_at(self, buf, offset)
347    }
348
349    #[inline]
350    fn read_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result<usize> {
351        filelike::read_vectored_at(self, bufs, offset)
352    }
353
354    #[inline]
355    fn read_exact_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result<()> {
356        filelike::read_exact_vectored_at(self, bufs, offset)
357    }
358
359    #[inline]
360    fn is_read_vectored_at(&self) -> bool {
361        filelike::is_read_vectored_at(self)
362    }
363
364    #[cfg(feature = "io-streams")]
365    #[inline]
366    fn read_via_stream_at(&self, offset: u64) -> io::Result<StreamReader> {
367        filelike::read_via_stream_at(self, offset)
368    }
369}
370
371impl ReadAt for ArrayEditor {
372    #[inline]
373    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
374        filelike::read_at(self, buf, offset)
375    }
376
377    #[inline]
378    fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
379        filelike::read_exact_at(self, buf, offset)
380    }
381
382    #[inline]
383    fn read_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result<usize> {
384        filelike::read_vectored_at(self, bufs, offset)
385    }
386
387    #[inline]
388    fn read_exact_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result<()> {
389        filelike::read_exact_vectored_at(self, bufs, offset)
390    }
391
392    #[inline]
393    fn is_read_vectored_at(&self) -> bool {
394        filelike::is_read_vectored_at(self)
395    }
396
397    #[cfg(feature = "io-streams")]
398    #[inline]
399    fn read_via_stream_at(&self, offset: u64) -> io::Result<StreamReader> {
400        filelike::read_via_stream_at(self, offset)
401    }
402}
403
404impl WriteAt for ArrayWriter {
405    #[inline]
406    fn write_at(&mut self, buf: &[u8], offset: u64) -> io::Result<usize> {
407        filelike::write_at(&*self, buf, offset)
408    }
409
410    #[inline]
411    fn write_all_at(&mut self, buf: &[u8], offset: u64) -> io::Result<()> {
412        filelike::write_all_at(&*self, buf, offset)
413    }
414
415    #[inline]
416    fn write_vectored_at(&mut self, bufs: &[IoSlice], offset: u64) -> io::Result<usize> {
417        filelike::write_vectored_at(&*self, bufs, offset)
418    }
419
420    #[inline]
421    fn write_all_vectored_at(&mut self, bufs: &mut [IoSlice], offset: u64) -> io::Result<()> {
422        filelike::write_all_vectored_at(&*self, bufs, offset)
423    }
424
425    #[inline]
426    fn is_write_vectored_at(&self) -> bool {
427        filelike::is_write_vectored_at(self)
428    }
429
430    #[inline]
431    fn copy_from<R: ReadAt>(
432        &mut self,
433        offset: u64,
434        input: &R,
435        input_offset: u64,
436        len: u64,
437    ) -> io::Result<u64> {
438        filelike::copy_from(&*self, offset, input, input_offset, len)
439    }
440
441    #[inline]
442    fn set_len(&mut self, size: u64) -> io::Result<()> {
443        filelike::set_len(&*self, size)
444    }
445}
446
447impl WriteAt for &ArrayWriter {
448    #[inline]
449    fn write_at(&mut self, buf: &[u8], offset: u64) -> io::Result<usize> {
450        filelike::write_at(&*self, buf, offset)
451    }
452
453    #[inline]
454    fn write_all_at(&mut self, buf: &[u8], offset: u64) -> io::Result<()> {
455        filelike::write_all_at(&*self, buf, offset)
456    }
457
458    #[inline]
459    fn write_vectored_at(&mut self, bufs: &[IoSlice], offset: u64) -> io::Result<usize> {
460        filelike::write_vectored_at(&*self, bufs, offset)
461    }
462
463    #[inline]
464    fn write_all_vectored_at(&mut self, bufs: &mut [IoSlice], offset: u64) -> io::Result<()> {
465        filelike::write_all_vectored_at(&*self, bufs, offset)
466    }
467
468    #[inline]
469    fn is_write_vectored_at(&self) -> bool {
470        filelike::is_write_vectored_at(self)
471    }
472
473    #[inline]
474    fn copy_from<R: ReadAt>(
475        &mut self,
476        offset: u64,
477        input: &R,
478        input_offset: u64,
479        len: u64,
480    ) -> io::Result<u64> {
481        filelike::copy_from(&*self, offset, input, input_offset, len)
482    }
483
484    #[inline]
485    fn set_len(&mut self, size: u64) -> io::Result<()> {
486        filelike::set_len(&*self, size)
487    }
488}
489
490impl WriteAt for ArrayEditor {
491    #[inline]
492    fn write_at(&mut self, buf: &[u8], offset: u64) -> io::Result<usize> {
493        filelike::write_at(&*self, buf, offset)
494    }
495
496    #[inline]
497    fn write_all_at(&mut self, buf: &[u8], offset: u64) -> io::Result<()> {
498        filelike::write_all_at(&*self, buf, offset)
499    }
500
501    #[inline]
502    fn write_vectored_at(&mut self, bufs: &[IoSlice], offset: u64) -> io::Result<usize> {
503        filelike::write_vectored_at(&*self, bufs, offset)
504    }
505
506    #[inline]
507    fn write_all_vectored_at(&mut self, bufs: &mut [IoSlice], offset: u64) -> io::Result<()> {
508        filelike::write_all_vectored_at(&*self, bufs, offset)
509    }
510
511    #[inline]
512    fn is_write_vectored_at(&self) -> bool {
513        filelike::is_write_vectored_at(self)
514    }
515
516    #[inline]
517    fn copy_from<R: ReadAt>(
518        &mut self,
519        offset: u64,
520        input: &R,
521        input_offset: u64,
522        len: u64,
523    ) -> io::Result<u64> {
524        filelike::copy_from(&*self, offset, input, input_offset, len)
525    }
526
527    #[inline]
528    fn set_len(&mut self, size: u64) -> io::Result<()> {
529        filelike::set_len(&*self, size)
530    }
531}
532
533impl WriteAt for &ArrayEditor {
534    #[inline]
535    fn write_at(&mut self, buf: &[u8], offset: u64) -> io::Result<usize> {
536        filelike::write_at(&*self, buf, offset)
537    }
538
539    #[inline]
540    fn write_all_at(&mut self, buf: &[u8], offset: u64) -> io::Result<()> {
541        filelike::write_all_at(&*self, buf, offset)
542    }
543
544    #[inline]
545    fn write_vectored_at(&mut self, bufs: &[IoSlice], offset: u64) -> io::Result<usize> {
546        filelike::write_vectored_at(&*self, bufs, offset)
547    }
548
549    #[inline]
550    fn write_all_vectored_at(&mut self, bufs: &mut [IoSlice], offset: u64) -> io::Result<()> {
551        filelike::write_all_vectored_at(&*self, bufs, offset)
552    }
553
554    #[inline]
555    fn is_write_vectored_at(&self) -> bool {
556        filelike::is_write_vectored_at(self)
557    }
558
559    #[inline]
560    fn copy_from<R: ReadAt>(
561        &mut self,
562        offset: u64,
563        input: &R,
564        input_offset: u64,
565        len: u64,
566    ) -> io::Result<u64> {
567        filelike::copy_from(&*self, offset, input, input_offset, len)
568    }
569
570    #[inline]
571    fn set_len(&mut self, size: u64) -> io::Result<()> {
572        filelike::set_len(&*self, size)
573    }
574}
575
576impl Array for fs::File {
577    #[inline]
578    fn metadata(&self) -> io::Result<Metadata> {
579        filelike::metadata(self)
580    }
581
582    #[inline]
583    fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
584        filelike::advise(self, offset, len, advice)
585    }
586}
587
588impl Array for &fs::File {
589    #[inline]
590    fn metadata(&self) -> io::Result<Metadata> {
591        filelike::metadata(self)
592    }
593
594    #[inline]
595    fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
596        filelike::advise(self, offset, len, advice)
597    }
598}
599
600impl ReadAt for fs::File {
601    #[inline]
602    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
603        filelike::read_at(self, buf, offset)
604    }
605
606    #[inline]
607    fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
608        filelike::read_exact_at(self, buf, offset)
609    }
610
611    #[inline]
612    fn read_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result<usize> {
613        filelike::read_vectored_at(self, bufs, offset)
614    }
615
616    #[inline]
617    fn read_exact_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result<()> {
618        filelike::read_exact_vectored_at(self, bufs, offset)
619    }
620
621    #[inline]
622    fn is_read_vectored_at(&self) -> bool {
623        filelike::is_read_vectored_at(self)
624    }
625
626    #[cfg(feature = "io-streams")]
627    #[inline]
628    fn read_via_stream_at(&self, offset: u64) -> io::Result<StreamReader> {
629        filelike::read_via_stream_at(self, offset)
630    }
631}
632
633impl WriteAt for fs::File {
634    #[inline]
635    fn write_at(&mut self, buf: &[u8], offset: u64) -> io::Result<usize> {
636        filelike::write_at(&*self, buf, offset)
637    }
638
639    #[inline]
640    fn write_all_at(&mut self, buf: &[u8], offset: u64) -> io::Result<()> {
641        filelike::write_all_at(&*self, buf, offset)
642    }
643
644    #[inline]
645    fn write_vectored_at(&mut self, bufs: &[IoSlice], offset: u64) -> io::Result<usize> {
646        filelike::write_vectored_at(&*self, bufs, offset)
647    }
648
649    #[inline]
650    fn write_all_vectored_at(&mut self, bufs: &mut [IoSlice], offset: u64) -> io::Result<()> {
651        filelike::write_all_vectored_at(&*self, bufs, offset)
652    }
653
654    #[inline]
655    fn is_write_vectored_at(&self) -> bool {
656        filelike::is_write_vectored_at(self)
657    }
658
659    #[inline]
660    fn copy_from<R: ReadAt>(
661        &mut self,
662        offset: u64,
663        input: &R,
664        input_offset: u64,
665        len: u64,
666    ) -> io::Result<u64> {
667        filelike::copy_from(&*self, offset, input, input_offset, len)
668    }
669
670    #[inline]
671    fn set_len(&mut self, size: u64) -> io::Result<()> {
672        filelike::set_len(&*self, size)
673    }
674}
675
676impl WriteAt for &fs::File {
677    #[inline]
678    fn write_at(&mut self, buf: &[u8], offset: u64) -> io::Result<usize> {
679        filelike::write_at(&*self, buf, offset)
680    }
681
682    #[inline]
683    fn write_all_at(&mut self, buf: &[u8], offset: u64) -> io::Result<()> {
684        filelike::write_all_at(&*self, buf, offset)
685    }
686
687    #[inline]
688    fn write_vectored_at(&mut self, bufs: &[IoSlice], offset: u64) -> io::Result<usize> {
689        filelike::write_vectored_at(&*self, bufs, offset)
690    }
691
692    #[inline]
693    fn write_all_vectored_at(&mut self, bufs: &mut [IoSlice], offset: u64) -> io::Result<()> {
694        filelike::write_all_vectored_at(&*self, bufs, offset)
695    }
696
697    #[inline]
698    fn is_write_vectored_at(&self) -> bool {
699        filelike::is_write_vectored_at(self)
700    }
701
702    #[inline]
703    fn copy_from<R: ReadAt>(
704        &mut self,
705        offset: u64,
706        input: &R,
707        input_offset: u64,
708        len: u64,
709    ) -> io::Result<u64> {
710        filelike::copy_from(&*self, offset, input, input_offset, len)
711    }
712
713    #[inline]
714    fn set_len(&mut self, size: u64) -> io::Result<()> {
715        filelike::set_len(&*self, size)
716    }
717}
718
719#[cfg(feature = "cap-std")]
720impl Array for cap_std::fs::File {
721    #[inline]
722    fn metadata(&self) -> io::Result<Metadata> {
723        filelike::metadata(self)
724    }
725
726    #[inline]
727    fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
728        filelike::advise(self, offset, len, advice)
729    }
730}
731
732#[cfg(feature = "cap-std")]
733impl Array for &cap_std::fs::File {
734    #[inline]
735    fn metadata(&self) -> io::Result<Metadata> {
736        filelike::metadata(self)
737    }
738
739    #[inline]
740    fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
741        filelike::advise(self, offset, len, advice)
742    }
743}
744
745#[cfg(feature = "cap-std")]
746impl ReadAt for cap_std::fs::File {
747    #[inline]
748    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
749        filelike::read_at(self, buf, offset)
750    }
751
752    #[inline]
753    fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
754        filelike::read_exact_at(self, buf, offset)
755    }
756
757    #[inline]
758    fn read_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result<usize> {
759        filelike::read_vectored_at(self, bufs, offset)
760    }
761
762    #[inline]
763    fn read_exact_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result<()> {
764        filelike::read_exact_vectored_at(self, bufs, offset)
765    }
766
767    #[inline]
768    fn is_read_vectored_at(&self) -> bool {
769        filelike::is_read_vectored_at(self)
770    }
771
772    #[cfg(feature = "io-streams")]
773    #[inline]
774    fn read_via_stream_at(&self, offset: u64) -> io::Result<StreamReader> {
775        filelike::read_via_stream_at(self, offset)
776    }
777}
778
779#[cfg(feature = "cap-std")]
780impl WriteAt for cap_std::fs::File {
781    #[inline]
782    fn write_at(&mut self, buf: &[u8], offset: u64) -> io::Result<usize> {
783        filelike::write_at(self, buf, offset)
784    }
785
786    #[inline]
787    fn write_all_at(&mut self, buf: &[u8], offset: u64) -> io::Result<()> {
788        filelike::write_all_at(self, buf, offset)
789    }
790
791    #[inline]
792    fn write_vectored_at(&mut self, bufs: &[IoSlice], offset: u64) -> io::Result<usize> {
793        filelike::write_vectored_at(self, bufs, offset)
794    }
795
796    #[inline]
797    fn write_all_vectored_at(&mut self, bufs: &mut [IoSlice], offset: u64) -> io::Result<()> {
798        filelike::write_all_vectored_at(self, bufs, offset)
799    }
800
801    #[inline]
802    fn is_write_vectored_at(&self) -> bool {
803        filelike::is_write_vectored_at(self)
804    }
805
806    #[inline]
807    fn copy_from<R: ReadAt>(
808        &mut self,
809        offset: u64,
810        input: &R,
811        input_offset: u64,
812        len: u64,
813    ) -> io::Result<u64> {
814        filelike::copy_from(self, offset, input, input_offset, len)
815    }
816
817    #[inline]
818    fn set_len(&mut self, size: u64) -> io::Result<()> {
819        filelike::set_len(self, size)
820    }
821}
822
823#[cfg(feature = "cap-std")]
824impl WriteAt for &cap_std::fs::File {
825    #[inline]
826    fn write_at(&mut self, buf: &[u8], offset: u64) -> io::Result<usize> {
827        filelike::write_at(self, buf, offset)
828    }
829
830    #[inline]
831    fn write_all_at(&mut self, buf: &[u8], offset: u64) -> io::Result<()> {
832        filelike::write_all_at(self, buf, offset)
833    }
834
835    #[inline]
836    fn write_vectored_at(&mut self, bufs: &[IoSlice], offset: u64) -> io::Result<usize> {
837        filelike::write_vectored_at(self, bufs, offset)
838    }
839
840    #[inline]
841    fn write_all_vectored_at(&mut self, bufs: &mut [IoSlice], offset: u64) -> io::Result<()> {
842        filelike::write_all_vectored_at(self, bufs, offset)
843    }
844
845    #[inline]
846    fn is_write_vectored_at(&self) -> bool {
847        filelike::is_write_vectored_at(self)
848    }
849
850    #[inline]
851    fn copy_from<R: ReadAt>(
852        &mut self,
853        offset: u64,
854        input: &R,
855        input_offset: u64,
856        len: u64,
857    ) -> io::Result<u64> {
858        filelike::copy_from(self, offset, input, input_offset, len)
859    }
860
861    #[inline]
862    fn set_len(&mut self, size: u64) -> io::Result<()> {
863        filelike::set_len(self, size)
864    }
865}
866
867/*
868#[cfg(feature = "cap-async-std")]
869impl Array for cap_async_std::fs::File {
870    #[inline]
871    fn metadata(&self) -> io::Result<Metadata> {
872        filelike::metadata(self)
873    }
874
875    #[inline]
876    fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
877        filelike::advise(self, offset, len, advice)
878    }
879}
880
881#[cfg(feature = "cap-async-std")]
882impl Array for &cap_async_std::fs::File {
883    #[inline]
884    fn metadata(&self) -> io::Result<Metadata> {
885        filelike::metadata(self)
886    }
887
888    #[inline]
889    fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
890        filelike::advise(self, offset, len, advice)
891    }
892}
893
894#[cfg(feature = "cap-async-std")]
895impl ReadAt for cap_async_std::fs::File {
896    #[inline]
897    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
898        filelike::read_at(self, buf, offset)
899    }
900
901    #[inline]
902    fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
903        filelike::read_exact_at(self, buf, offset)
904    }
905
906    #[inline]
907    fn read_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result<usize> {
908        filelike::read_vectored_at(self, bufs, offset)
909    }
910
911    #[inline]
912    fn read_exact_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result<()> {
913        filelike::read_exact_vectored_at(self, bufs, offset)
914    }
915
916    #[inline]
917    fn is_read_vectored_at(&self) -> bool {
918        filelike::is_read_vectored_at(self)
919    }
920
921    #[cfg(feature = "io-streams")]
922    #[inline]
923    fn read_via_stream_at(&self, offset: u64) -> io::Result<StreamReader> {
924        filelike::read_via_stream_at(self, offset)
925    }
926}
927
928#[cfg(feature = "cap-async-std")]
929impl WriteAt for cap_async_std::fs::File {
930    #[inline]
931    fn write_at(&mut self, buf: &[u8], offset: u64) -> io::Result<usize> {
932        filelike::write_at(self, buf, offset)
933    }
934
935    #[inline]
936    fn write_all_at(&mut self, buf: &[u8], offset: u64) -> io::Result<()> {
937        filelike::write_all_at(self, buf, offset)
938    }
939
940    #[inline]
941    fn write_vectored_at(&mut self, bufs: &[IoSlice], offset: u64) -> io::Result<usize> {
942        filelike::write_vectored_at(self, bufs, offset)
943    }
944
945    #[inline]
946    fn write_all_vectored_at(&mut self, bufs: &mut [IoSlice], offset: u64) -> io::Result<()> {
947        filelike::write_all_vectored_at(self, bufs, offset)
948    }
949
950    #[inline]
951    fn is_write_vectored_at(&self) -> bool {
952        filelike::is_write_vectored_at(self)
953    }
954
955    #[inline]
956    fn copy_from<R: ReadAt>(
957        &mut self,
958        offset: u64,
959        input: &R,
960        input_offset: u64,
961        len: u64,
962    ) -> io::Result<u64> {
963        filelike::copy_from(self, offset, input, input_offset, len)
964    }
965
966    #[inline]
967    fn set_len(&mut self, size: u64) -> io::Result<()> {
968        filelike::set_len(self, size)
969    }
970}
971
972#[cfg(feature = "cap-async-std")]
973impl WriteAt for &cap_async_std::fs::File {
974    #[inline]
975    fn write_at(&mut self, buf: &[u8], offset: u64) -> io::Result<usize> {
976        filelike::write_at(self, buf, offset)
977    }
978
979    #[inline]
980    fn write_all_at(&mut self, buf: &[u8], offset: u64) -> io::Result<()> {
981        filelike::write_all_at(self, buf, offset)
982    }
983
984    #[inline]
985    fn write_vectored_at(&mut self, bufs: &[IoSlice], offset: u64) -> io::Result<usize> {
986        filelike::write_vectored_at(self, bufs, offset)
987    }
988
989    #[inline]
990    fn write_all_vectored_at(&mut self, bufs: &mut [IoSlice], offset: u64) -> io::Result<()> {
991        filelike::write_all_vectored_at(self, bufs, offset)
992    }
993
994    #[inline]
995    fn is_write_vectored_at(&self) -> bool {
996        filelike::is_write_vectored_at(self)
997    }
998
999    #[inline]
1000    fn copy_from<R: ReadAt>(
1001        &mut self,
1002        offset: u64,
1003        input: &R,
1004        input_offset: u64,
1005        len: u64,
1006    ) -> io::Result<u64> {
1007        filelike::copy_from(self, offset, input, input_offset, len)
1008    }
1009
1010    #[inline]
1011    fn set_len(&mut self, size: u64) -> io::Result<()> {
1012        filelike::set_len(self, size)
1013    }
1014}
1015
1016#[cfg(feature = "async-std")]
1017impl Array for async_std::fs::File {
1018    #[inline]
1019    fn metadata(&self) -> io::Result<Metadata> {
1020        filelike::metadata(self)
1021    }
1022
1023    #[inline]
1024    fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
1025        filelike::advise(self, offset, len, advice)
1026    }
1027}
1028
1029#[cfg(feature = "async-std")]
1030impl Array for &async_std::fs::File {
1031    #[inline]
1032    fn metadata(&self) -> io::Result<Metadata> {
1033        filelike::metadata(self)
1034    }
1035
1036    #[inline]
1037    fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
1038        filelike::advise(self, offset, len, advice)
1039    }
1040}
1041
1042#[cfg(feature = "async-std")]
1043impl ReadAt for async_std::fs::File {
1044    #[inline]
1045    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
1046        filelike::read_at(self, buf, offset)
1047    }
1048
1049    #[inline]
1050    fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
1051        filelike::read_exact_at(self, buf, offset)
1052    }
1053
1054    #[inline]
1055    fn read_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result<usize> {
1056        filelike::read_vectored_at(self, bufs, offset)
1057    }
1058
1059    #[inline]
1060    fn read_exact_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result<()> {
1061        filelike::read_exact_vectored_at(self, bufs, offset)
1062    }
1063
1064    #[inline]
1065    fn is_read_vectored_at(&self) -> bool {
1066        filelike::is_read_vectored_at(self)
1067    }
1068
1069    #[cfg(feature = "io-streams")]
1070    #[inline]
1071    fn read_via_stream_at(&self, offset: u64) -> io::Result<StreamReader> {
1072        filelike::read_via_stream_at(self, offset)
1073    }
1074}
1075
1076#[cfg(feature = "async-std")]
1077impl WriteAt for async_std::fs::File {
1078    #[inline]
1079    fn write_at(&mut self, buf: &[u8], offset: u64) -> io::Result<usize> {
1080        filelike::write_at(self, buf, offset)
1081    }
1082
1083    #[inline]
1084    fn write_all_at(&mut self, buf: &[u8], offset: u64) -> io::Result<()> {
1085        filelike::write_all_at(self, buf, offset)
1086    }
1087
1088    #[inline]
1089    fn write_vectored_at(&mut self, bufs: &[IoSlice], offset: u64) -> io::Result<usize> {
1090        filelike::write_vectored_at(self, bufs, offset)
1091    }
1092
1093    #[inline]
1094    fn write_all_vectored_at(&mut self, bufs: &mut [IoSlice], offset: u64) -> io::Result<()> {
1095        filelike::write_all_vectored_at(self, bufs, offset)
1096    }
1097
1098    #[inline]
1099    fn is_write_vectored_at(&self) -> bool {
1100        filelike::is_write_vectored_at(self)
1101    }
1102
1103    #[inline]
1104    fn copy_from<R: ReadAt>(
1105        &mut self,
1106        offset: u64,
1107        input: &R,
1108        input_offset: u64,
1109        len: u64,
1110    ) -> io::Result<u64> {
1111        filelike::copy_from(self, offset, input, input_offset, len)
1112    }
1113
1114    #[inline]
1115    fn set_len(&mut self, size: u64) -> io::Result<()> {
1116        filelike::set_len(self, size)
1117    }
1118}
1119
1120#[cfg(feature = "async-std")]
1121impl WriteAt for &async_std::fs::File {
1122    #[inline]
1123    fn write_at(&mut self, buf: &[u8], offset: u64) -> io::Result<usize> {
1124        filelike::write_at(self, buf, offset)
1125    }
1126
1127    #[inline]
1128    fn write_all_at(&mut self, buf: &[u8], offset: u64) -> io::Result<()> {
1129        filelike::write_all_at(self, buf, offset)
1130    }
1131
1132    #[inline]
1133    fn write_vectored_at(&mut self, bufs: &[IoSlice], offset: u64) -> io::Result<usize> {
1134        filelike::write_vectored_at(self, bufs, offset)
1135    }
1136
1137    #[inline]
1138    fn write_all_vectored_at(&mut self, bufs: &mut [IoSlice], offset: u64) -> io::Result<()> {
1139        filelike::write_all_vectored_at(self, bufs, offset)
1140    }
1141
1142    #[inline]
1143    fn is_write_vectored_at(&self) -> bool {
1144        filelike::is_write_vectored_at(self)
1145    }
1146
1147    #[inline]
1148    fn copy_from<R: ReadAt>(
1149        &mut self,
1150        offset: u64,
1151        input: &R,
1152        input_offset: u64,
1153        len: u64,
1154    ) -> io::Result<u64> {
1155        filelike::copy_from(self, offset, input, input_offset, len)
1156    }
1157
1158    #[inline]
1159    fn set_len(&mut self, size: u64) -> io::Result<()> {
1160        filelike::set_len(self, size)
1161    }
1162}
1163*/
1164
1165#[cfg(not(windows))]
1166impl AsRawFd for ArrayReader {
1167    #[inline]
1168    fn as_raw_fd(&self) -> RawFd {
1169        self.file.as_raw_fd()
1170    }
1171}
1172
1173#[cfg(not(windows))]
1174impl AsFd for ArrayReader {
1175    #[inline]
1176    fn as_fd(&self) -> BorrowedFd<'_> {
1177        self.file.as_fd()
1178    }
1179}
1180
1181#[cfg(windows)]
1182impl AsRawHandle for ArrayReader {
1183    #[inline]
1184    fn as_raw_handle(&self) -> RawHandle {
1185        self.file.as_raw_handle()
1186    }
1187}
1188
1189#[cfg(windows)]
1190impl AsHandle for ArrayReader {
1191    #[inline]
1192    fn as_handle(&self) -> BorrowedHandle<'_> {
1193        self.file.as_handle()
1194    }
1195}
1196
1197#[cfg(windows)]
1198impl AsRawHandleOrSocket for ArrayReader {
1199    #[inline]
1200    fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
1201        self.file.as_raw_handle_or_socket()
1202    }
1203}
1204
1205#[cfg(not(windows))]
1206impl AsRawFd for ArrayWriter {
1207    #[inline]
1208    fn as_raw_fd(&self) -> RawFd {
1209        self.file.as_raw_fd()
1210    }
1211}
1212
1213#[cfg(not(windows))]
1214impl AsFd for ArrayWriter {
1215    #[inline]
1216    fn as_fd(&self) -> BorrowedFd<'_> {
1217        self.file.as_fd()
1218    }
1219}
1220
1221#[cfg(windows)]
1222impl AsRawHandle for ArrayWriter {
1223    #[inline]
1224    fn as_raw_handle(&self) -> RawHandle {
1225        self.file.as_raw_handle()
1226    }
1227}
1228
1229#[cfg(windows)]
1230impl AsHandle for ArrayWriter {
1231    #[inline]
1232    fn as_handle(&self) -> BorrowedHandle<'_> {
1233        self.file.as_handle()
1234    }
1235}
1236
1237#[cfg(windows)]
1238impl AsRawHandleOrSocket for ArrayWriter {
1239    #[inline]
1240    fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
1241        self.file.as_raw_handle_or_socket()
1242    }
1243}
1244
1245#[cfg(not(windows))]
1246impl AsRawFd for ArrayEditor {
1247    #[inline]
1248    fn as_raw_fd(&self) -> RawFd {
1249        self.file.as_raw_fd()
1250    }
1251}
1252
1253#[cfg(not(windows))]
1254impl AsFd for ArrayEditor {
1255    #[inline]
1256    fn as_fd(&self) -> BorrowedFd<'_> {
1257        self.file.as_fd()
1258    }
1259}
1260
1261#[cfg(windows)]
1262impl AsRawHandle for ArrayEditor {
1263    #[inline]
1264    fn as_raw_handle(&self) -> RawHandle {
1265        self.file.as_raw_handle()
1266    }
1267}
1268
1269#[cfg(windows)]
1270impl AsHandle for ArrayEditor {
1271    #[inline]
1272    fn as_handle(&self) -> BorrowedHandle<'_> {
1273        self.file.as_handle()
1274    }
1275}
1276
1277#[cfg(windows)]
1278impl AsRawHandleOrSocket for ArrayEditor {
1279    #[inline]
1280    fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
1281        self.file.as_raw_handle_or_socket()
1282    }
1283}
1284
1285// On Linux, use `memfd_create`.
1286#[cfg(any(target_os = "android", target_os = "linux"))]
1287fn create_anonymous() -> io::Result<rustix::fd::OwnedFd> {
1288    let flags = rustix::fs::MemfdFlags::CLOEXEC | rustix::fs::MemfdFlags::ALLOW_SEALING;
1289    let name = rustix::cstr!("io_arrays anonymous file");
1290    Ok(rustix::fs::memfd_create(name, flags)?)
1291}
1292
1293// Otherwise, use a temporary file.
1294#[cfg(not(any(target_os = "android", target_os = "linux")))]
1295fn create_anonymous() -> io::Result<OwnedFilelike> {
1296    let file = tempfile::tempfile()?;
1297    Ok(file.into_filelike())
1298}