Skip to main content

qubit_fs/traits/
file_system_ext.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10//! Convenience extension methods for [`crate::FileSystem`].
11
12use std::io::{
13    Read,
14    Write,
15};
16
17use crate::{
18    FileSystem,
19    FsError,
20    FsErrorKind,
21    FsOperation,
22    FsPath,
23    FsResult,
24    ReadOptions,
25    WriteOptions,
26    WriteOutcome,
27};
28
29/// Convenience methods for filesystem trait objects.
30pub trait FileSystemExt {
31    /// Reads an entire resource into memory.
32    ///
33    /// # Parameters
34    /// - `path`: Resource path.
35    ///
36    /// # Returns
37    /// Resource bytes.
38    ///
39    /// # Errors
40    /// Returns [`crate::FsError`] when opening or reading fails.
41    fn read_all(&self, path: &FsPath) -> FsResult<Vec<u8>>;
42
43    /// Writes an entire resource and commits the writer.
44    ///
45    /// # Parameters
46    /// - `path`: Resource path.
47    /// - `bytes`: Bytes to write.
48    ///
49    /// # Returns
50    /// Write outcome.
51    ///
52    /// # Errors
53    /// Returns [`crate::FsError`] when opening, writing, or committing fails.
54    fn write_all(&self, path: &FsPath, bytes: &[u8]) -> FsResult<WriteOutcome>;
55}
56
57impl<T> FileSystemExt for T
58where
59    T: FileSystem + ?Sized,
60{
61    fn read_all(&self, path: &FsPath) -> FsResult<Vec<u8>> {
62        let mut reader = self.open_reader(path, &ReadOptions::default())?;
63        let mut bytes = Vec::new();
64        reader.read_to_end(&mut bytes).map_err(|error| {
65            FsError::with_source(
66                FsErrorKind::Io,
67                FsOperation::OpenReader,
68                "failed to read resource",
69                error,
70            )
71            .with_path(path.clone())
72        })?;
73        Ok(bytes)
74    }
75
76    fn write_all(&self, path: &FsPath, bytes: &[u8]) -> FsResult<WriteOutcome> {
77        let mut writer = self.open_writer(path, &WriteOptions::default())?;
78        if let Err(error) = writer.write_all(bytes) {
79            let _ = writer.abort();
80            return Err(FsError::with_source(
81                FsErrorKind::Io,
82                FsOperation::OpenWriter,
83                "failed to write resource",
84                error,
85            )
86            .with_path(path.clone()));
87        }
88        writer.commit()
89    }
90}