1use std::{
2 cell::UnsafeCell,
3 ffi::OsStr,
4 fmt::{self, Write},
5 marker::PhantomData,
6 mem::MaybeUninit,
7 panic::{RefUnwindSafe, UnwindSafe},
8 path::Path,
9 sync::Once,
10};
11
12pub(super) struct JoinOsStrs<'a, T> {
13 pub(super) slice: &'a [T],
14 pub(super) delimiter: char,
15}
16
17impl<T> fmt::Display for JoinOsStrs<'_, T>
18where
19 T: AsRef<OsStr>,
20{
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 let len = self.slice.len();
23 for (index, os_str) in self.slice.iter().enumerate() {
24 write!(f, "{}", Path::new(os_str).display())?;
27 if index + 1 < len {
28 f.write_char(self.delimiter)?;
29 }
30 }
31 Ok(())
32 }
33}
34
35pub(super) struct OptionOsStrDisplay<T>(pub(super) Option<T>);
36
37impl<T> fmt::Display for OptionOsStrDisplay<T>
38where
39 T: AsRef<OsStr>,
40{
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 if let Some(os_str) = self.0.as_ref() {
45 write!(f, "Some({})", Path::new(os_str).display())
46 } else {
47 f.write_str("None")
48 }
49 }
50}
51
52pub(crate) struct OnceLock<T> {
53 once: Once,
54 value: UnsafeCell<MaybeUninit<T>>,
55 _marker: PhantomData<T>,
56}
57
58impl<T> Default for OnceLock<T> {
59 fn default() -> Self {
60 Self::new()
61 }
62}
63
64impl<T> OnceLock<T> {
65 pub(crate) const fn new() -> Self {
66 Self {
67 once: Once::new(),
68 value: UnsafeCell::new(MaybeUninit::uninit()),
69 _marker: PhantomData,
70 }
71 }
72
73 #[inline]
74 fn is_initialized(&self) -> bool {
75 self.once.is_completed()
76 }
77
78 unsafe fn get_unchecked(&self) -> &T {
79 debug_assert!(self.is_initialized());
80 #[allow(clippy::needless_borrow)]
81 #[allow(unused_unsafe)]
82 unsafe {
83 (&*self.value.get()).assume_init_ref()
84 }
85 }
86
87 pub(crate) fn get_or_init(&self, f: impl FnOnce() -> T) -> &T {
88 self.once.call_once(|| {
89 unsafe { &mut *self.value.get() }.write(f());
90 });
91 unsafe { self.get_unchecked() }
92 }
93
94 pub(crate) fn get(&self) -> Option<&T> {
95 if self.is_initialized() {
96 Some(unsafe { self.get_unchecked() })
98 } else {
99 None
100 }
101 }
102}
103
104impl<T: fmt::Debug> fmt::Debug for OnceLock<T> {
105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106 let mut d = f.debug_tuple("OnceLock");
107 match self.get() {
108 Some(v) => d.field(v),
109 None => d.field(&format_args!("<uninit>")),
110 };
111 d.finish()
112 }
113}
114
115unsafe impl<T: Sync + Send> Sync for OnceLock<T> {}
116unsafe impl<T: Send> Send for OnceLock<T> {}
117
118impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T> {}
119impl<T: UnwindSafe> UnwindSafe for OnceLock<T> {}
120
121impl<T> Drop for OnceLock<T> {
122 #[inline]
123 fn drop(&mut self) {
124 if self.once.is_completed() {
125 unsafe { self.value.get_mut().assume_init_drop() };
128 }
129 }
130}