qubit_fs/temp/temp_resource_factory.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//! Temporary resource factory trait.
11
12use std::fmt::Debug;
13use std::process;
14use std::sync::Arc;
15use std::sync::atomic::{
16 AtomicU64,
17 Ordering,
18};
19use std::time::{
20 SystemTime,
21 UNIX_EPOCH,
22};
23
24use crate::{
25 FileSystem,
26 FsPath,
27 FsResult,
28 TempDir,
29 TempDirOptions,
30 TempFile,
31 TempFileOptions,
32};
33
34/// Global counter used to reduce temporary name collision risk.
35static TEMP_COUNTER: AtomicU64 = AtomicU64::new(0);
36
37/// Factory for filesystem-owned temporary resources.
38pub trait TempResourceFactory: Debug + Send + Sync {
39 /// Creates a temporary file.
40 ///
41 /// # Parameters
42 /// - `owner`: Filesystem that will own the temporary file.
43 /// - `options`: Temporary file creation options.
44 ///
45 /// # Returns
46 /// Temporary file handle with cleanup responsibility.
47 ///
48 /// # Errors
49 /// Returns [`crate::FsError`] when the temporary file cannot be created.
50 fn create_file(&self, owner: Arc<dyn FileSystem>, options: &TempFileOptions) -> FsResult<Box<dyn TempFile>>;
51
52 /// Creates a temporary directory.
53 ///
54 /// # Parameters
55 /// - `owner`: Filesystem that will own the temporary directory.
56 /// - `options`: Temporary directory creation options.
57 ///
58 /// # Returns
59 /// Temporary directory handle with cleanup responsibility.
60 ///
61 /// # Errors
62 /// Returns [`crate::FsError`] when the temporary directory cannot be
63 /// created.
64 fn create_dir(&self, owner: Arc<dyn FileSystem>, options: &TempDirOptions) -> FsResult<Box<dyn TempDir>>;
65
66 /// Builds a temporary resource path using the common rs-fs naming format.
67 ///
68 /// The default format is `{prefix}{process_id}-{unix_epoch_nanos}-{counter}{suffix}`.
69 /// Implementations may use this helper to share the common format, or ignore
70 /// it and apply provider-specific naming rules.
71 ///
72 /// # Parameters
73 /// - `parent`: Optional parent path. Root is used when absent.
74 /// - `prefix`: Temporary name prefix.
75 /// - `suffix`: Temporary name suffix.
76 ///
77 /// # Returns
78 /// Generated temporary path.
79 ///
80 /// # Errors
81 /// Returns [`crate::FsError`] when the generated path is invalid.
82 fn make_temp_path(&self, parent: Option<&FsPath>, prefix: &str, suffix: &str) -> FsResult<FsPath> {
83 let parent = parent.cloned().unwrap_or_else(FsPath::root);
84 let counter = TEMP_COUNTER.fetch_add(1, Ordering::Relaxed);
85 let nanos = SystemTime::now()
86 .duration_since(UNIX_EPOCH)
87 .unwrap_or_default()
88 .as_nanos();
89 let name = format!("{prefix}{}-{nanos}-{counter}{suffix}", process::id());
90 parent.join(&name)
91 }
92}