Skip to content

Commit e18cfb7

Browse files
authored
Merge pull request #4 from sunsided/feature/random-names
Add new and new_in without uuid dependency
2 parents d6e1ced + bf771d2 commit e18cfb7

File tree

6 files changed

+93
-29
lines changed

6 files changed

+93
-29
lines changed

.github/workflows/rust.yml

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,21 @@ env:
1111

1212
jobs:
1313
build:
14-
1514
runs-on: ubuntu-latest
16-
15+
strategy:
16+
matrix:
17+
features: [[], ["--all-features"]]
1718
steps:
18-
- uses: actions/checkout@v3
19-
- name: Check Formatting
20-
run: cargo fmt --check
21-
- name: Clippy
22-
run: cargo clippy
23-
- name: Build
24-
run: cargo build --verbose
25-
- name: Run build tests
26-
run: cargo build --tests --all-features
27-
- name: Run tests
28-
run: cargo test --tests --all-features --verbose
29-
- name: Run doctests
30-
run: cargo test --doc --all-features --verbose
19+
- uses: actions/checkout@v2
20+
- name: Check Formatting
21+
run: cargo fmt --check
22+
- name: Clippy
23+
run: cargo clippy ${{ join(matrix.features, ' ') }}
24+
- name: Build
25+
run: cargo build --verbose ${{ join(matrix.features, ' ') }}
26+
- name: Run build tests
27+
run: cargo build --tests ${{ join(matrix.features, ' ') }}
28+
- name: Run tests
29+
run: cargo test --tests --verbose ${{ join(matrix.features, ' ') }}
30+
- name: Run doctests
31+
run: cargo test --doc --verbose ${{ join(matrix.features, ' ') }}

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ This project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

88
### Changed
99

10+
- The `new` and `new_in` functions now do not rely on the `uuid` feature anymore
11+
for the generation of temporary file names.
1012
- The `uuid` feature is now not enabled by default anymore.
1113

1214
### Internal

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ uuid = ["dep:uuid"]
1818
[[test]]
1919
name = "tests"
2020
path = "tests/tests.rs"
21-
required-features = ["uuid"]
2221

2322
[dependencies]
2423
tokio = { version = "1.34.0", features = ["fs"] }

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use async_tempfile::TempFile;
99

1010
#[tokio::main]
1111
async fn main() {
12-
// NOTE: The new() function is available with the `uuid` crate feature.
1312
let parent = TempFile::new().await.unwrap();
1413

1514
// The cloned reference will not delete the file when dropped.

src/lib.rs

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,14 @@ use std::path::PathBuf;
4444
use std::pin::Pin;
4545
use std::sync::Arc;
4646
use std::task::{Context, Poll};
47+
use std::time::SystemTime;
4748
use tokio::fs::{File, OpenOptions};
4849
use tokio::io::{AsyncRead, AsyncSeek, AsyncWrite, ReadBuf};
4950

5051
#[cfg(feature = "uuid")]
5152
use uuid::Uuid;
5253

53-
#[cfg(feature = "uuid")]
54-
const FILE_PREFIX: &'static str = "atmp_";
54+
const FILE_PREFIX: &str = "atmp_";
5555

5656
/// A named temporary file that will be cleaned automatically
5757
/// after the last reference to it is dropped.
@@ -115,8 +115,6 @@ impl TempFile {
115115
/// # Ok::<(), Error>(())
116116
/// # });
117117
/// ```
118-
#[cfg_attr(docsrs, doc(cfg(feature = "uuid")))]
119-
#[cfg(feature = "uuid")]
120118
pub async fn new() -> Result<Self, Error> {
121119
Self::new_in(Self::default_dir()).await
122120
}
@@ -189,6 +187,11 @@ impl TempFile {
189187
/// Creates a new temporary file in the specified location.
190188
/// When the instance goes out of scope, the file will be deleted.
191189
///
190+
/// ## Crate Features
191+
///
192+
/// * `uuid` - When the `uuid` crate feature is enabled, a random UUIDv4 is used to
193+
/// generate the temporary file name.
194+
///
192195
/// ## Arguments
193196
///
194197
/// * `dir` - The directory to create the file in.
@@ -213,12 +216,18 @@ impl TempFile {
213216
/// assert!(fs::metadata(file_path).await.is_err());
214217
/// # Ok::<(), Error>(())
215218
/// # });
216-
/// ```
217-
#[cfg_attr(docsrs, doc(cfg(feature = "uuid")))]
218-
#[cfg(feature = "uuid")]
219219
pub async fn new_in<P: Borrow<PathBuf>>(dir: P) -> Result<Self, Error> {
220-
let id = Uuid::new_v4();
221-
return Self::new_with_uuid_in(id, dir).await;
220+
#[cfg(feature = "uuid")]
221+
{
222+
let id = Uuid::new_v4();
223+
Self::new_with_uuid_in(id, dir).await
224+
}
225+
226+
#[cfg(not(feature = "uuid"))]
227+
{
228+
let name = RandomName::new();
229+
Self::new_with_name_in(name, dir).await
230+
}
222231
}
223232

224233
/// Creates a new temporary file in the specified location.
@@ -405,6 +414,40 @@ impl TempFile {
405414
}
406415
}
407416

417+
/// Represents a randomly generated file name.
418+
struct RandomName {
419+
name: String,
420+
}
421+
422+
impl RandomName {
423+
#[allow(dead_code)]
424+
fn new() -> Self {
425+
let pid = std::process::id();
426+
427+
// Using the address of a local variable for extra variation.
428+
let marker = &pid as *const _ as usize;
429+
430+
// Current timestamp for added variation.
431+
let now = SystemTime::now()
432+
.duration_since(SystemTime::UNIX_EPOCH)
433+
.unwrap_or(std::time::Duration::from_secs(0));
434+
let (secs, subsec_nanos) = (now.as_secs(), now.subsec_nanos());
435+
436+
Self {
437+
name: format!(
438+
"{}{}{:x}{:x}{:x}",
439+
FILE_PREFIX, pid, marker, secs, subsec_nanos
440+
),
441+
}
442+
}
443+
}
444+
445+
impl AsRef<str> for RandomName {
446+
fn as_ref(&self) -> &str {
447+
&self.name
448+
}
449+
}
450+
408451
/// Ensures the file handles are closed before the core reference is freed.
409452
/// If the core reference would be freed while handles are still open, it is
410453
/// possible that the underlying file cannot be deleted.
@@ -535,3 +578,14 @@ impl AsyncSeek for TempFile {
535578
Pin::new(self.file.deref_mut()).poll_complete(cx)
536579
}
537580
}
581+
582+
#[cfg(test)]
583+
mod tests {
584+
use super::*;
585+
586+
#[test]
587+
fn test_random_name() {
588+
let name = RandomName::new();
589+
assert!(name.as_ref().starts_with(FILE_PREFIX))
590+
}
591+
}

tests/tests.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1-
use async_tempfile::{Ownership, TempFile};
1+
use async_tempfile::TempFile;
2+
3+
#[cfg(feature = "uuid")]
4+
use async_tempfile::Ownership;
5+
6+
#[cfg(feature = "uuid")]
27
use tokio::fs::OpenOptions;
8+
9+
#[cfg(feature = "uuid")]
310
use uuid::Uuid;
411

512
#[tokio::test]
@@ -41,7 +48,8 @@ async fn ro_file_is_not_dropped_while_still_referenced() {
4148
}
4249

4350
#[tokio::test]
44-
async fn borrowed_file_is_not_dropped() {
51+
#[cfg(feature = "uuid")]
52+
async fn uuid_borrowed_file_is_not_dropped() {
4553
let file_name = format!("test_{}", Uuid::new_v4());
4654
let path = std::env::temp_dir().join(file_name);
4755
let _original = OpenOptions::new()
@@ -64,7 +72,8 @@ async fn borrowed_file_is_not_dropped() {
6472
}
6573

6674
#[tokio::test]
67-
async fn owned_file_is_dropped() {
75+
#[cfg(feature = "uuid")]
76+
async fn uuid_owned_file_is_dropped() {
6877
let file_name = format!("test_{}", Uuid::new_v4());
6978
let path = std::env::temp_dir().join(file_name);
7079
let _original = OpenOptions::new()

0 commit comments

Comments
 (0)