@@ -94,15 +94,25 @@ impl<T: Into<Self> + 'static> MaybeDyn<T> {
94
94
}
95
95
}
96
96
97
- impl < T : Into < Self > > From < ReadSignal < T > > for MaybeDyn < T > {
98
- fn from ( val : ReadSignal < T > ) -> Self {
99
- MaybeDyn :: Signal ( val)
97
+ impl < T : Into < Self > , U : Into < MaybeDyn < T > > + Clone > From < ReadSignal < U > > for MaybeDyn < T > {
98
+ fn from ( val : ReadSignal < U > ) -> Self {
99
+ // Check if U == T, i.e. ReadSignal<U> is actually a ReadSignal<T>.
100
+ //
101
+ // If so, we use a trick to convert the generic type to the concrete type. This should be
102
+ // optimized out by the compiler to be zero-cost.
103
+ if let Some ( val) =
104
+ ( & mut Some ( val) as & mut dyn std:: any:: Any ) . downcast_mut :: < Option < ReadSignal < T > > > ( )
105
+ {
106
+ MaybeDyn :: Signal ( val. unwrap ( ) )
107
+ } else {
108
+ MaybeDyn :: Derived ( Rc :: new ( move || val. get_clone ( ) . into ( ) ) )
109
+ }
100
110
}
101
111
}
102
112
103
- impl < T : Into < Self > > From < Signal < T > > for MaybeDyn < T > {
104
- fn from ( val : Signal < T > ) -> Self {
105
- MaybeDyn :: Signal ( * val)
113
+ impl < T : Into < Self > , U : Into < MaybeDyn < T > > + Clone > From < Signal < U > > for MaybeDyn < T > {
114
+ fn from ( val : Signal < U > ) -> Self {
115
+ Self :: from ( * val)
106
116
}
107
117
}
108
118
@@ -149,20 +159,39 @@ macro_rules! impl_into_maybe_dyn {
149
159
}
150
160
}
151
161
162
+ $crate:: impl_into_maybe_dyn_with_convert!( $ty; Into :: into $( ; $( $from) ,* ) ?) ;
163
+ } ;
164
+ }
165
+
166
+ /// Create `From<U>` implementations for `MaybeDyn<T>` for a list of types.
167
+ ///
168
+ /// Usually, you would use the [`impl_into_maybe_dyn!`] macro instead of this macro.
169
+ #[ macro_export]
170
+ macro_rules! impl_into_maybe_dyn_with_convert {
171
+ ( $ty: ty; $convert: expr $( ; $( $from: ty) ,* ) ?) => {
152
172
$(
153
173
$(
154
174
impl From <$from> for $crate:: MaybeDyn <$ty> {
155
175
fn from( val: $from) -> Self {
156
- MaybeDyn :: Static ( val . into ( ) )
176
+ MaybeDyn :: Static ( $convert ( val ) )
157
177
}
158
178
}
159
179
) *
160
180
) ?
161
181
} ;
162
182
}
163
183
164
- impl_into_maybe_dyn ! ( bool ) ;
165
184
impl_into_maybe_dyn ! ( Cow <' static , str >; & ' static str , String ) ;
185
+ impl_into_maybe_dyn_with_convert ! (
186
+ Option <Cow <' static , str >>; |x| Some ( Into :: into( x) ) ;
187
+ Cow <' static , str >, & ' static str , String
188
+ ) ;
189
+ impl_into_maybe_dyn_with_convert ! (
190
+ Option <Cow <' static , str >>; |x| Option :: map( x, Into :: into) ;
191
+ Option <& ' static str >, Option <String >
192
+ ) ;
193
+
194
+ impl_into_maybe_dyn ! ( bool ) ;
166
195
167
196
impl_into_maybe_dyn ! ( f32 ) ;
168
197
impl_into_maybe_dyn ! ( f64 ) ;
@@ -180,6 +209,12 @@ impl_into_maybe_dyn!(u64);
180
209
impl_into_maybe_dyn ! ( u128 ) ;
181
210
impl_into_maybe_dyn ! ( usize ) ;
182
211
212
+ impl < T > From < Option < T > > for MaybeDyn < Option < T > > {
213
+ fn from ( val : Option < T > ) -> Self {
214
+ MaybeDyn :: Static ( val)
215
+ }
216
+ }
217
+
183
218
impl < T > From < Vec < T > > for MaybeDyn < Vec < T > > {
184
219
fn from ( val : Vec < T > ) -> Self {
185
220
MaybeDyn :: Static ( val)
@@ -209,14 +244,27 @@ mod tests {
209
244
fn maybe_dyn_signal ( ) {
210
245
let _ = create_root ( move || {
211
246
let signal = create_signal ( 123 ) ;
212
- let value = MaybeDyn :: from ( signal) ;
213
- assert ! ( value. as_static( ) . is_none( ) ) ;
247
+ let value = MaybeDyn :: < i32 > :: from ( signal) ;
248
+ assert ! ( matches!( value, MaybeDyn :: Signal ( _) ) ) ;
249
+
214
250
assert_eq ! ( value. get( ) , 123 ) ;
215
251
assert_eq ! ( value. get_clone( ) , 123 ) ;
216
252
assert_eq ! ( value. evaluate( ) , 123 ) ;
217
253
} ) ;
218
254
}
219
255
256
+ #[ test]
257
+ fn maybe_dyn_signal_from ( ) {
258
+ let _ = create_root ( move || {
259
+ let signal = create_signal ( "abc" ) ;
260
+ let value = MaybeDyn :: < Cow < ' static , str > > :: from ( signal) ;
261
+ assert ! ( matches!( value, MaybeDyn :: Derived ( _) ) ) ;
262
+
263
+ assert_eq ! ( value. get_clone( ) , "abc" ) ;
264
+ assert_eq ! ( value. evaluate( ) , "abc" ) ;
265
+ } ) ;
266
+ }
267
+
220
268
#[ test]
221
269
fn maybe_dyn_derived ( ) {
222
270
let value = MaybeDyn :: < i32 > :: from ( || 123 ) ;
0 commit comments