]> git.proxmox.com Git - cargo.git/blame - vendor/tempfile/src/util.rs
New upstream version 0.35.0
[cargo.git] / vendor / tempfile / src / util.rs
CommitLineData
22758248
XL
1use rand::distributions::Alphanumeric;
2use rand::{self, Rng};
3use std::ffi::{OsStr, OsString};
f8611cf8 4use std::path::{Path, PathBuf};
22758248 5use std::{io, str};
f8611cf8 6
2f2e175c
VK
7use error::IoResultExt;
8
22758248
XL
9fn tmpname(prefix: &OsStr, suffix: &OsStr, rand_len: usize) -> OsString {
10 let mut buf = OsString::with_capacity(prefix.len() + suffix.len() + rand_len);
11 buf.push(prefix);
f8611cf8 12
22758248
XL
13 // Push each character in one-by-one. Unfortunately, this is the only
14 // safe(ish) simple way to do this without allocating a temporary
15 // String/Vec.
f8611cf8 16 unsafe {
22758248
XL
17 rand::thread_rng()
18 .sample_iter(&Alphanumeric)
19 .take(rand_len)
20 .for_each(|b| buf.push(str::from_utf8_unchecked(&[b as u8])))
f8611cf8 21 }
22758248
XL
22 buf.push(suffix);
23 buf
f8611cf8
VK
24}
25
26pub fn create_helper<F, R>(
27 base: &Path,
22758248
XL
28 prefix: &OsStr,
29 suffix: &OsStr,
f8611cf8
VK
30 random_len: usize,
31 f: F,
32) -> io::Result<R>
33where
34 F: Fn(PathBuf) -> io::Result<R>,
35{
2f2e175c
VK
36 let num_retries = if random_len != 0 { ::NUM_RETRIES } else { 1 };
37
38 for _ in 0..num_retries {
f8611cf8
VK
39 let path = base.join(tmpname(prefix, suffix, random_len));
40 return match f(path) {
41 Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => continue,
42 res => res,
43 };
44 }
45
46 Err(io::Error::new(
22758248
XL
47 io::ErrorKind::AlreadyExists,
48 "too many temporary files exist",
49 ))
50 .with_err_path(|| base)
f8611cf8 51}