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}