@@ -5,8 +5,8 @@ use std::fmt::{Debug, Display};
5
5
use std:: ops:: Deref ;
6
6
use std:: sync:: LazyLock ;
7
7
8
- enum MaybeLazyInner < T : ' static + ToOwned + ?Sized > {
9
- Lazy ( LazyLock < T :: Owned > ) ,
8
+ enum MaybeLazyInner < T : ' static + ToOwned + ?Sized , F > {
9
+ Lazy ( LazyLock < T :: Owned , F > ) ,
10
10
Cow ( Cow < ' static , T > ) ,
11
11
}
12
12
@@ -16,16 +16,16 @@ enum MaybeLazyInner<T: 'static + ToOwned + ?Sized> {
16
16
/// They can all be constructed from the [`MaybeLazy::borrowed`], [`MaybeLazy::owned`] and
17
17
/// [`MaybeLazy::lazy`] methods.
18
18
#[ repr( transparent) ]
19
- pub struct MaybeLazy < T : ' static + ToOwned + ?Sized > {
19
+ pub struct MaybeLazy < T : ' static + ToOwned + ?Sized , F = fn ( ) -> < T as ToOwned > :: Owned > {
20
20
// Inner state.
21
21
//
22
22
// Not to be inlined since we may want in the future to
23
23
// make this struct usable to statics and we might need to
24
24
// workaround const-eval limitation (particulary around drop).
25
- inner : MaybeLazyInner < T > ,
25
+ inner : MaybeLazyInner < T , F > ,
26
26
}
27
27
28
- impl < T : ' static + ?Sized + ToOwned > MaybeLazy < T > {
28
+ impl < T : ' static + ?Sized + ToOwned , F : FnOnce ( ) -> T :: Owned > MaybeLazy < T , F > {
29
29
/// Create a [`MaybeLazy`] from an borrowed `T`.
30
30
#[ inline]
31
31
pub const fn borrowed ( a : & ' static T ) -> Self {
@@ -38,17 +38,24 @@ impl<T: 'static + ?Sized + ToOwned> MaybeLazy<T> {
38
38
MaybeLazy { inner : MaybeLazyInner :: Cow ( Cow :: Owned ( a) ) }
39
39
}
40
40
41
- /// Create a [`MaybeLazy`] that is lazy by taking a function pointer.
42
- ///
43
- /// This function pointer cannot *ever* take a closure. User can potentially
44
- /// workaround that by using closure-to-fnptr or `const` items.
41
+ /// Create a [`MaybeLazy`] from a function-able `F`.
42
+ #[ inline]
43
+ pub const fn lazied ( f : F ) -> Self {
44
+ MaybeLazy { inner : MaybeLazyInner :: Lazy ( LazyLock :: new ( f) ) }
45
+ }
46
+ }
47
+
48
+ impl < T : ' static + ?Sized + ToOwned > MaybeLazy < T > {
49
+ /// Create a [`MaybeLazy`] from a function pointer.
45
50
#[ inline]
46
51
pub const fn lazy ( a : fn ( ) -> T :: Owned ) -> Self {
47
- MaybeLazy { inner : MaybeLazyInner :: Lazy ( LazyLock :: new ( a ) ) }
52
+ Self :: lazied ( a )
48
53
}
49
54
}
50
55
51
- impl < T : ' static + ?Sized + ToOwned < Owned : Clone > > Clone for MaybeLazy < T > {
56
+ impl < T : ' static + ?Sized + ToOwned < Owned : Clone > , F : FnOnce ( ) -> T :: Owned > Clone
57
+ for MaybeLazy < T , F >
58
+ {
52
59
#[ inline]
53
60
fn clone ( & self ) -> Self {
54
61
MaybeLazy {
@@ -60,15 +67,19 @@ impl<T: 'static + ?Sized + ToOwned<Owned: Clone>> Clone for MaybeLazy<T> {
60
67
}
61
68
}
62
69
63
- impl < T : ' static + ?Sized + ToOwned < Owned : Default > > Default for MaybeLazy < T > {
70
+ impl < T : ' static + ?Sized + ToOwned < Owned : Default > , F : FnOnce ( ) -> T :: Owned > Default
71
+ for MaybeLazy < T , F >
72
+ {
64
73
#[ inline]
65
- fn default ( ) -> MaybeLazy < T > {
66
- MaybeLazy :: lazy ( T :: Owned :: default)
74
+ fn default ( ) -> MaybeLazy < T , F > {
75
+ MaybeLazy :: owned ( T :: Owned :: default ( ) )
67
76
}
68
77
}
69
78
70
79
// `Debug`, `Display` and other traits below are implemented in terms of this `Deref`
71
- impl < T : ' static + ?Sized + ToOwned < Owned : Borrow < T > > > Deref for MaybeLazy < T > {
80
+ impl < T : ' static + ?Sized + ToOwned < Owned : Borrow < T > > , F : FnOnce ( ) -> T :: Owned > Deref
81
+ for MaybeLazy < T , F >
82
+ {
72
83
type Target = T ;
73
84
74
85
#[ inline]
@@ -80,46 +91,54 @@ impl<T: 'static + ?Sized + ToOwned<Owned: Borrow<T>>> Deref for MaybeLazy<T> {
80
91
}
81
92
}
82
93
83
- impl < T : ' static + ?Sized + ToOwned < Owned : Debug > + Debug > Debug for MaybeLazy < T > {
94
+ impl < T : ' static + ?Sized + ToOwned < Owned : Debug > + Debug , F : FnOnce ( ) -> T :: Owned > Debug
95
+ for MaybeLazy < T , F >
96
+ {
84
97
#[ inline]
85
98
fn fmt ( & self , fmt : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
86
99
Debug :: fmt ( & * * self , fmt)
87
100
}
88
101
}
89
102
90
- impl < T : ' static + ?Sized + ToOwned < Owned : Display > + Display > Display for MaybeLazy < T > {
103
+ impl < T : ' static + ?Sized + ToOwned < Owned : Display > + Display , F : FnOnce ( ) -> T :: Owned > Display
104
+ for MaybeLazy < T , F >
105
+ {
91
106
#[ inline]
92
107
fn fmt ( & self , fmt : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
93
108
Display :: fmt ( & * * self , fmt)
94
109
}
95
110
}
96
111
97
- impl < T : ' static + ?Sized + ToOwned > AsRef < T > for MaybeLazy < T > {
112
+ impl < T : ' static + ?Sized + ToOwned , F : FnOnce ( ) -> T :: Owned > AsRef < T > for MaybeLazy < T , F > {
98
113
#[ inline]
99
114
fn as_ref ( & self ) -> & T {
100
115
& * * self
101
116
}
102
117
}
103
118
104
- impl < B : ?Sized + PartialEq < C > + ToOwned , C : ?Sized + ToOwned > PartialEq < MaybeLazy < C > >
105
- for MaybeLazy < B >
119
+ impl <
120
+ T1 : ?Sized + PartialEq < T2 > + ToOwned ,
121
+ T2 : ?Sized + ToOwned ,
122
+ F1 : FnOnce ( ) -> T1 :: Owned ,
123
+ F2 : FnOnce ( ) -> T2 :: Owned ,
124
+ > PartialEq < MaybeLazy < T2 , F2 > > for MaybeLazy < T1 , F1 >
106
125
{
107
126
#[ inline]
108
- fn eq ( & self , other : & MaybeLazy < C > ) -> bool {
127
+ fn eq ( & self , other : & MaybeLazy < T2 , F2 > ) -> bool {
109
128
PartialEq :: eq ( & * * self , & * * other)
110
129
}
111
130
}
112
131
113
- impl PartialEq < & str > for MaybeLazy < str > {
132
+ impl < F : FnOnce ( ) -> String > PartialEq < & str > for MaybeLazy < str , F > {
114
133
#[ inline]
115
134
fn eq ( & self , other : & & str ) -> bool {
116
135
& * * self == * other
117
136
}
118
137
}
119
138
120
- impl From < & ' static str > for MaybeLazy < str > {
139
+ impl < F : FnOnce ( ) -> String > From < & ' static str > for MaybeLazy < str , F > {
121
140
#[ inline]
122
- fn from ( s : & ' static str ) -> MaybeLazy < str > {
141
+ fn from ( s : & ' static str ) -> MaybeLazy < str , F > {
123
142
MaybeLazy :: borrowed ( s)
124
143
}
125
144
}
0 commit comments