1use alef_core::ir::{CoreWrapper, PrimitiveType, TypeDef, TypeRef};
2use std::fmt::Write;
3
4use super::ConversionConfig;
5use super::helpers::{core_prim_str, core_type_path, is_newtype, is_tuple_type_name, needs_i64_cast};
6
7pub fn gen_from_binding_to_core(typ: &TypeDef, core_import: &str) -> String {
10 gen_from_binding_to_core_cfg(typ, core_import, &ConversionConfig::default())
11}
12
13pub fn gen_from_binding_to_core_cfg(typ: &TypeDef, core_import: &str, config: &ConversionConfig) -> String {
15 let core_path = core_type_path(typ, core_import);
16 let binding_name = format!("{}{}", config.type_name_prefix, typ.name);
17 let mut out = String::with_capacity(256);
18 if typ.has_stripped_cfg_fields {
21 writeln!(out, "#[allow(clippy::needless_update)]").ok();
22 }
23 let uses_builder_pattern = config.option_duration_on_defaults
25 && typ.has_default
26 && typ
27 .fields
28 .iter()
29 .any(|f| !f.optional && matches!(f.ty, TypeRef::Duration));
30 if uses_builder_pattern {
31 writeln!(out, "#[allow(clippy::field_reassign_with_default)]").ok();
32 }
33 writeln!(out, "impl From<{binding_name}> for {core_path} {{").ok();
34 writeln!(out, " fn from(val: {binding_name}) -> Self {{").ok();
35
36 if is_newtype(typ) {
38 let field = &typ.fields[0];
39 let inner_expr = match &field.ty {
40 TypeRef::Named(_) => "val._0.into()".to_string(),
41 TypeRef::Path => "val._0.into()".to_string(),
42 TypeRef::Duration => "std::time::Duration::from_millis(val._0)".to_string(),
43 _ => "val._0".to_string(),
44 };
45 writeln!(out, " Self({inner_expr})").ok();
46 writeln!(out, " }}").ok();
47 write!(out, "}}").ok();
48 return out;
49 }
50
51 let has_optionalized_duration = config.option_duration_on_defaults
56 && typ.has_default
57 && typ
58 .fields
59 .iter()
60 .any(|f| !f.optional && matches!(f.ty, TypeRef::Duration));
61
62 if has_optionalized_duration {
63 writeln!(out, " let mut __result = {core_path}::default();").ok();
65 let optionalized = config.optionalize_defaults && typ.has_default;
66 for field in &typ.fields {
67 if field.cfg.is_some() {
69 continue;
70 }
71 if field.sanitized {
72 continue;
74 }
75 if !config.exclude_types.is_empty()
77 && super::helpers::field_references_excluded_type(&field.ty, config.exclude_types)
78 {
79 continue;
80 }
81 if !field.optional && matches!(field.ty, TypeRef::Duration) {
83 let cast = if config.cast_large_ints_to_i64 { " as u64" } else { "" };
84 writeln!(
85 out,
86 " if let Some(__v) = val.{} {{ __result.{} = std::time::Duration::from_millis(__v{cast}); }}",
87 field.name, field.name
88 )
89 .ok();
90 continue;
91 }
92 let conversion = if optionalized && !field.optional {
93 gen_optionalized_field_to_core(&field.name, &field.ty, config)
94 } else {
95 field_conversion_to_core_cfg(&field.name, &field.ty, field.optional, config)
96 };
97 if let Some(expr) = conversion.strip_prefix(&format!("{}: ", field.name)) {
99 writeln!(out, " __result.{} = {};", field.name, expr).ok();
100 }
101 }
102 writeln!(out, " __result").ok();
103 writeln!(out, " }}").ok();
104 write!(out, "}}").ok();
105 return out;
106 }
107
108 writeln!(out, " Self {{").ok();
109 let optionalized = config.optionalize_defaults && typ.has_default;
110 for field in &typ.fields {
111 if field.cfg.is_some() {
116 continue;
117 }
118 let references_excluded = !config.exclude_types.is_empty()
125 && super::helpers::field_references_excluded_type(&field.ty, config.exclude_types);
126 if references_excluded && typ.has_stripped_cfg_fields {
127 continue;
128 }
129 let conversion = if field.sanitized || references_excluded {
130 format!("{}: Default::default()", field.name)
131 } else if optionalized && !field.optional {
132 gen_optionalized_field_to_core(&field.name, &field.ty, config)
135 } else {
136 field_conversion_to_core_cfg(&field.name, &field.ty, field.optional, config)
137 };
138 let conversion = if let Some(newtype_path) = &field.newtype_wrapper {
144 if let Some(expr) = conversion.strip_prefix(&format!("{}: ", field.name)) {
145 match &field.ty {
148 TypeRef::Optional(_) => format!("{}: ({expr}).map({newtype_path})", field.name),
149 TypeRef::Vec(_) => {
150 format!("{}: ({expr}).into_iter().map({newtype_path}).collect()", field.name)
151 }
152 _ if field.optional => format!("{}: ({expr}).map({newtype_path})", field.name),
153 _ => format!("{}: {newtype_path}({expr})", field.name),
154 }
155 } else {
156 conversion
157 }
158 } else {
159 conversion
160 };
161 let conversion = if field.is_boxed && matches!(&field.ty, TypeRef::Named(_)) {
163 if let Some(expr) = conversion.strip_prefix(&format!("{}: ", field.name)) {
164 if field.optional {
165 format!("{}: {}.map(Box::new)", field.name, expr)
167 } else {
168 format!("{}: Box::new({})", field.name, expr)
169 }
170 } else {
171 conversion
172 }
173 } else {
174 conversion
175 };
176 let conversion = apply_core_wrapper_to_core(
178 &conversion,
179 &field.name,
180 &field.core_wrapper,
181 &field.vec_inner_core_wrapper,
182 field.optional,
183 );
184 writeln!(out, " {conversion},").ok();
185 }
186 if typ.has_stripped_cfg_fields {
188 writeln!(out, " ..Default::default()").ok();
189 }
190 writeln!(out, " }}").ok();
191 writeln!(out, " }}").ok();
192 write!(out, "}}").ok();
193 out
194}
195
196pub(super) fn gen_optionalized_field_to_core(name: &str, ty: &TypeRef, config: &ConversionConfig) -> String {
199 match ty {
200 TypeRef::Json => {
201 format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok()).unwrap_or_default()")
202 }
203 TypeRef::Named(_) => {
204 format!("{name}: val.{name}.map(Into::into).unwrap_or_default()")
206 }
207 TypeRef::Primitive(PrimitiveType::F32) if config.cast_f32_to_f64 => {
208 format!("{name}: val.{name}.map(|v| v as f32).unwrap_or(0.0)")
209 }
210 TypeRef::Primitive(PrimitiveType::F32 | PrimitiveType::F64) => {
211 format!("{name}: val.{name}.unwrap_or(0.0)")
212 }
213 TypeRef::Primitive(p) if config.cast_large_ints_to_i64 && needs_i64_cast(p) => {
214 let core_ty = core_prim_str(p);
215 format!("{name}: val.{name}.map(|v| v as {core_ty}).unwrap_or_default()")
216 }
217 TypeRef::Optional(inner)
218 if config.cast_large_ints_to_i64
219 && matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
220 {
221 if let TypeRef::Primitive(p) = inner.as_ref() {
222 let core_ty = core_prim_str(p);
223 format!("{name}: val.{name}.map(|v| v as {core_ty})")
224 } else {
225 field_conversion_to_core(name, ty, false)
226 }
227 }
228 TypeRef::Duration if config.cast_large_ints_to_i64 => {
229 format!("{name}: val.{name}.map(|v| std::time::Duration::from_millis(v as u64)).unwrap_or_default()")
230 }
231 TypeRef::Duration => {
232 format!("{name}: val.{name}.map(std::time::Duration::from_millis).unwrap_or_default()")
233 }
234 TypeRef::Path => {
235 format!("{name}: val.{name}.map(Into::into).unwrap_or_default()")
236 }
237 TypeRef::Optional(inner) if matches!(inner.as_ref(), TypeRef::Path) => {
238 format!("{name}: val.{name}.map(|s| std::path::PathBuf::from(s))")
240 }
241 TypeRef::Optional(_) => {
242 format!("{name}: val.{name}.map(Some)")
245 }
246 TypeRef::Char => {
248 format!("{name}: val.{name}.and_then(|s| s.chars().next()).unwrap_or('*')")
249 }
250 TypeRef::Vec(inner) => match inner.as_ref() {
251 TypeRef::Json => {
252 format!(
253 "{name}: val.{name}.map(|v| v.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect()).unwrap_or_default()"
254 )
255 }
256 TypeRef::Named(_) => {
257 format!("{name}: val.{name}.map(|v| v.into_iter().map(Into::into).collect()).unwrap_or_default()")
258 }
259 TypeRef::Primitive(p) if config.cast_large_ints_to_i64 && needs_i64_cast(p) => {
260 let core_ty = core_prim_str(p);
261 format!(
262 "{name}: val.{name}.map(|v| v.into_iter().map(|x| x as {core_ty}).collect()).unwrap_or_default()"
263 )
264 }
265 _ => format!("{name}: val.{name}.unwrap_or_default()"),
266 },
267 TypeRef::Map(k, v) if matches!(v.as_ref(), TypeRef::Json) => {
268 let k_is_json = matches!(k.as_ref(), TypeRef::Json);
270 let k_expr = if k_is_json {
271 "serde_json::from_str(&k).unwrap_or_default()"
272 } else {
273 "k"
274 };
275 format!(
276 "{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| ({k_expr}, serde_json::from_str(&v).unwrap_or(serde_json::json!(v)))).collect()"
277 )
278 }
279 TypeRef::Map(k, _v) if matches!(k.as_ref(), TypeRef::Json) => {
280 format!(
282 "{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (serde_json::from_str(&k).unwrap_or_default(), v)).collect()"
283 )
284 }
285 TypeRef::Map(k, v) => {
286 let has_named_val = matches!(v.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n));
288 if has_named_val {
289 format!("{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (k, v.into())).collect()")
290 } else if matches!(k.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n)) {
291 format!("{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (k.into(), v)).collect()")
292 } else {
293 format!("{name}: val.{name}.unwrap_or_default().into_iter().collect()")
294 }
295 }
296 _ => {
297 format!("{name}: val.{name}.unwrap_or_default()")
299 }
300 }
301}
302
303pub fn field_conversion_to_core(name: &str, ty: &TypeRef, optional: bool) -> String {
305 match ty {
306 TypeRef::Primitive(_) | TypeRef::String | TypeRef::Bytes | TypeRef::Unit => {
308 format!("{name}: val.{name}")
309 }
310 TypeRef::Json => {
312 if optional {
313 format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok())")
314 } else {
315 format!("{name}: serde_json::from_str(&val.{name}).unwrap_or_default()")
316 }
317 }
318 TypeRef::Char => {
320 if optional {
321 format!("{name}: val.{name}.and_then(|s| s.chars().next())")
322 } else {
323 format!("{name}: val.{name}.chars().next().unwrap_or('*')")
324 }
325 }
326 TypeRef::Duration => {
328 if optional {
329 format!("{name}: val.{name}.map(std::time::Duration::from_millis)")
330 } else {
331 format!("{name}: std::time::Duration::from_millis(val.{name})")
332 }
333 }
334 TypeRef::Path => {
336 if optional {
337 format!("{name}: val.{name}.map(Into::into)")
338 } else {
339 format!("{name}: val.{name}.into()")
340 }
341 }
342 TypeRef::Named(type_name) if is_tuple_type_name(type_name) => {
345 format!("{name}: val.{name}")
346 }
347 TypeRef::Named(_) => {
348 if optional {
349 format!("{name}: val.{name}.map(Into::into)")
350 } else {
351 format!("{name}: val.{name}.into()")
352 }
353 }
354 TypeRef::Map(k, v) if matches!(v.as_ref(), TypeRef::Json) => {
356 let k_expr = if matches!(k.as_ref(), TypeRef::Json) {
357 "serde_json::from_str(&k).unwrap_or_default()"
358 } else {
359 "k"
360 };
361 if optional {
362 format!(
363 "{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| ({k_expr}, serde_json::from_str(&v).unwrap_or_default())).collect())"
364 )
365 } else {
366 format!(
367 "{name}: val.{name}.into_iter().map(|(k, v)| ({k_expr}, serde_json::from_str(&v).unwrap_or_default())).collect()"
368 )
369 }
370 }
371 TypeRef::Optional(inner) => match inner.as_ref() {
373 TypeRef::Json => format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok())"),
374 TypeRef::Named(_) | TypeRef::Path => format!("{name}: val.{name}.map(Into::into)"),
375 TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Named(_)) => {
376 format!("{name}: val.{name}.map(|v| v.into_iter().map(Into::into).collect())")
377 }
378 _ => format!("{name}: val.{name}"),
379 },
380 TypeRef::Vec(inner) => match inner.as_ref() {
382 TypeRef::Json => {
383 if optional {
384 format!(
385 "{name}: val.{name}.map(|v| v.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect())"
386 )
387 } else {
388 format!("{name}: val.{name}.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect()")
389 }
390 }
391 TypeRef::Named(type_name) if is_tuple_type_name(type_name) => {
393 format!("{name}: val.{name}")
394 }
395 TypeRef::Named(_) => {
396 if optional {
397 format!("{name}: val.{name}.map(|v| v.into_iter().map(Into::into).collect())")
398 } else {
399 format!("{name}: val.{name}.into_iter().map(Into::into).collect()")
400 }
401 }
402 _ => format!("{name}: val.{name}"),
403 },
404 TypeRef::Map(k, v) => {
407 let has_named_key = matches!(k.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n));
408 let has_named_val = matches!(v.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n));
409 let has_json_val = matches!(v.as_ref(), TypeRef::Json);
410 let has_json_key = matches!(k.as_ref(), TypeRef::Json);
411 let has_vec_named_val = matches!(v.as_ref(), TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n)));
413 let has_vec_json_val = matches!(v.as_ref(), TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Json));
415 if has_json_val || has_json_key || has_named_key || has_named_val || has_vec_named_val || has_vec_json_val {
416 let k_expr = if has_json_key {
417 "serde_json::from_str(&k).unwrap_or(serde_json::Value::String(k))"
418 } else if has_named_key {
419 "k.into()"
420 } else {
421 "k"
422 };
423 let v_expr = if has_json_val {
424 "serde_json::from_str(&v).unwrap_or(serde_json::Value::String(v))"
425 } else if has_named_val {
426 "v.into()"
427 } else if has_vec_named_val {
428 "v.into_iter().map(Into::into).collect()"
429 } else if has_vec_json_val {
430 "v.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect()"
431 } else {
432 "v"
433 };
434 if optional {
435 format!("{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| ({k_expr}, {v_expr})).collect())")
436 } else {
437 format!("{name}: val.{name}.into_iter().map(|(k, v)| ({k_expr}, {v_expr})).collect()")
438 }
439 } else {
440 if optional {
442 format!("{name}: val.{name}.map(|m| m.into_iter().collect())")
443 } else {
444 format!("{name}: val.{name}.into_iter().collect()")
445 }
446 }
447 }
448 }
449}
450
451pub fn field_conversion_to_core_cfg(name: &str, ty: &TypeRef, optional: bool, config: &ConversionConfig) -> String {
453 if optional && matches!(ty, TypeRef::Optional(_)) {
457 let inner_expr = field_conversion_to_core_cfg(name, ty, false, config);
460 if let Some(expr) = inner_expr.strip_prefix(&format!("{name}: ")) {
462 return format!("{name}: ({expr}).map(Some)");
463 }
464 return inner_expr;
465 }
466
467 if config.map_uses_jsvalue {
469 let is_nested_vec = matches!(ty, TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Vec(_)));
470 let is_vec_json = matches!(ty, TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Json));
471 let is_map = matches!(ty, TypeRef::Map(_, _));
472 if is_nested_vec || is_map || is_vec_json {
473 if optional {
474 return format!(
475 "{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::from_value(v.clone()).ok())"
476 );
477 }
478 return format!("{name}: serde_wasm_bindgen::from_value(val.{name}.clone()).unwrap_or_default()");
479 }
480 if let TypeRef::Optional(inner) = ty {
481 let is_inner_nested = matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Vec(_)));
482 let is_inner_vec_json = matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Json));
483 let is_inner_map = matches!(inner.as_ref(), TypeRef::Map(_, _));
484 if is_inner_nested || is_inner_map || is_inner_vec_json {
485 return format!(
486 "{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::from_value(v.clone()).ok())"
487 );
488 }
489 }
490 }
491
492 if config.vec_named_to_string {
496 if let TypeRef::Vec(_) = ty {
497 if optional {
498 return format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok())");
499 }
500 return format!("{name}: serde_json::from_str(&val.{name}).unwrap_or_default()");
501 }
502 }
503 if config.json_to_string && matches!(ty, TypeRef::Json) {
505 return format!("{name}: Default::default()");
506 }
507 if config.map_uses_jsvalue && matches!(ty, TypeRef::Json) {
509 if optional {
510 return format!("{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::from_value(v.clone()).ok())");
511 }
512 return format!("{name}: serde_wasm_bindgen::from_value(val.{name}.clone()).unwrap_or_default()");
513 }
514 if !config.cast_large_ints_to_i64
515 && !config.cast_f32_to_f64
516 && !config.json_to_string
517 && !config.vec_named_to_string
518 {
519 return field_conversion_to_core(name, ty, optional);
520 }
521 match ty {
523 TypeRef::Primitive(p) if config.cast_large_ints_to_i64 && needs_i64_cast(p) => {
524 let core_ty = core_prim_str(p);
525 if optional {
526 format!("{name}: val.{name}.map(|v| v as {core_ty})")
527 } else {
528 format!("{name}: val.{name} as {core_ty}")
529 }
530 }
531 TypeRef::Primitive(PrimitiveType::F32) if config.cast_f32_to_f64 => {
533 if optional {
534 format!("{name}: val.{name}.map(|v| v as f32)")
535 } else {
536 format!("{name}: val.{name} as f32")
537 }
538 }
539 TypeRef::Duration if config.cast_large_ints_to_i64 => {
540 if optional {
541 format!("{name}: val.{name}.map(|v| std::time::Duration::from_millis(v as u64))")
542 } else {
543 format!("{name}: std::time::Duration::from_millis(val.{name} as u64)")
544 }
545 }
546 TypeRef::Optional(inner) if matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) => {
547 if let TypeRef::Primitive(p) = inner.as_ref() {
548 let core_ty = core_prim_str(p);
549 format!("{name}: val.{name}.map(|v| v as {core_ty})")
550 } else {
551 field_conversion_to_core(name, ty, optional)
552 }
553 }
554 TypeRef::Vec(inner)
556 if config.cast_large_ints_to_i64
557 && matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
558 {
559 if let TypeRef::Primitive(p) = inner.as_ref() {
560 let core_ty = core_prim_str(p);
561 if optional {
562 format!("{name}: val.{name}.map(|v| v.into_iter().map(|x| x as {core_ty}).collect())")
563 } else {
564 format!("{name}: val.{name}.into_iter().map(|v| v as {core_ty}).collect()")
565 }
566 } else {
567 field_conversion_to_core(name, ty, optional)
568 }
569 }
570 TypeRef::Map(_k, v)
572 if config.cast_large_ints_to_i64 && matches!(v.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
573 {
574 if let TypeRef::Primitive(p) = v.as_ref() {
575 let core_ty = core_prim_str(p);
576 if optional {
577 format!("{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| (k, v as {core_ty})).collect())")
578 } else {
579 format!("{name}: val.{name}.into_iter().map(|(k, v)| (k, v as {core_ty})).collect()")
580 }
581 } else {
582 field_conversion_to_core(name, ty, optional)
583 }
584 }
585 TypeRef::Vec(inner)
587 if config.cast_f32_to_f64 && matches!(inner.as_ref(), TypeRef::Primitive(PrimitiveType::F32)) =>
588 {
589 if optional {
590 format!("{name}: val.{name}.map(|v| v.into_iter().map(|x| x as f32).collect())")
591 } else {
592 format!("{name}: val.{name}.into_iter().map(|v| v as f32).collect()")
593 }
594 }
595 TypeRef::Optional(inner)
597 if config.cast_f32_to_f64
598 && matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Primitive(PrimitiveType::F32))) =>
599 {
600 format!("{name}: val.{name}.map(|v| v.into_iter().map(|x| x as f32).collect())")
601 }
602 _ => field_conversion_to_core(name, ty, optional),
604 }
605}
606
607fn apply_core_wrapper_to_core(
610 conversion: &str,
611 name: &str,
612 core_wrapper: &CoreWrapper,
613 vec_inner_core_wrapper: &CoreWrapper,
614 optional: bool,
615) -> String {
616 if *vec_inner_core_wrapper == CoreWrapper::Arc {
618 return conversion
619 .replace(
620 ".map(Into::into).collect()",
621 ".map(|v| std::sync::Arc::new(v.into())).collect()",
622 )
623 .replace(
624 "map(|v| v.into_iter().map(Into::into)",
625 "map(|v| v.into_iter().map(|v| std::sync::Arc::new(v.into()))",
626 );
627 }
628
629 match core_wrapper {
630 CoreWrapper::None => conversion.to_string(),
631 CoreWrapper::Cow => {
632 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
636 if optional {
637 format!("{name}: {expr}.map(Into::into)")
638 } else if expr == format!("val.{name}") {
639 format!("{name}: val.{name}.into()")
640 } else if expr == "Default::default()" {
641 conversion.to_string()
644 } else {
645 format!("{name}: ({expr}).into()")
646 }
647 } else {
648 conversion.to_string()
649 }
650 }
651 CoreWrapper::Arc => {
652 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
654 if expr == "Default::default()" {
655 conversion.to_string()
658 } else if optional {
659 format!("{name}: {expr}.map(|v| std::sync::Arc::new(v))")
660 } else {
661 format!("{name}: std::sync::Arc::new({expr})")
662 }
663 } else {
664 conversion.to_string()
665 }
666 }
667 CoreWrapper::Bytes => {
668 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
670 if optional {
671 format!("{name}: {expr}.map(Into::into)")
672 } else if expr == format!("val.{name}") {
673 format!("{name}: val.{name}.into()")
674 } else if expr == "Default::default()" {
675 conversion.to_string()
678 } else {
679 format!("{name}: ({expr}).into()")
680 }
681 } else {
682 conversion.to_string()
683 }
684 }
685 CoreWrapper::ArcMutex => {
686 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
688 if optional {
689 format!("{name}: {expr}.map(|v| std::sync::Arc::new(std::sync::Mutex::new(v.into())))")
690 } else if expr == format!("val.{name}") {
691 format!("{name}: std::sync::Arc::new(std::sync::Mutex::new(val.{name}.into()))")
692 } else {
693 format!("{name}: std::sync::Arc::new(std::sync::Mutex::new(({expr}).into()))")
694 }
695 } else {
696 conversion.to_string()
697 }
698 }
699 }
700}