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 is_opaque_arc_field = field.core_wrapper == CoreWrapper::Arc
184 && matches!(&field.ty, TypeRef::Named(n) if config
185 .opaque_types
186 .is_some_and(|opaque| opaque.contains(n.as_str())));
187 let conversion = if is_opaque_arc_field {
188 if field.optional {
189 format!("{}: val.{}.map(|v| v.inner)", field.name, field.name)
190 } else {
191 format!("{}: val.{}.inner", field.name, field.name)
192 }
193 } else {
194 apply_core_wrapper_to_core(
195 &conversion,
196 &field.name,
197 &field.core_wrapper,
198 &field.vec_inner_core_wrapper,
199 field.optional,
200 )
201 };
202 writeln!(out, " {conversion},").ok();
203 }
204 if typ.has_stripped_cfg_fields {
206 writeln!(out, " ..Default::default()").ok();
207 }
208 writeln!(out, " }}").ok();
209 writeln!(out, " }}").ok();
210 write!(out, "}}").ok();
211 out
212}
213
214pub(super) fn gen_optionalized_field_to_core(name: &str, ty: &TypeRef, config: &ConversionConfig) -> String {
217 match ty {
218 TypeRef::Json => {
219 format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok()).unwrap_or_default()")
220 }
221 TypeRef::Named(_) => {
222 format!("{name}: val.{name}.map(Into::into).unwrap_or_default()")
224 }
225 TypeRef::Primitive(PrimitiveType::F32) if config.cast_f32_to_f64 => {
226 format!("{name}: val.{name}.map(|v| v as f32).unwrap_or(0.0)")
227 }
228 TypeRef::Primitive(PrimitiveType::F32 | PrimitiveType::F64) => {
229 format!("{name}: val.{name}.unwrap_or(0.0)")
230 }
231 TypeRef::Primitive(p) if config.cast_large_ints_to_i64 && needs_i64_cast(p) => {
232 let core_ty = core_prim_str(p);
233 format!("{name}: val.{name}.map(|v| v as {core_ty}).unwrap_or_default()")
234 }
235 TypeRef::Optional(inner)
236 if config.cast_large_ints_to_i64
237 && matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
238 {
239 if let TypeRef::Primitive(p) = inner.as_ref() {
240 let core_ty = core_prim_str(p);
241 format!("{name}: val.{name}.map(|v| v as {core_ty})")
242 } else {
243 field_conversion_to_core(name, ty, false)
244 }
245 }
246 TypeRef::Duration if config.cast_large_ints_to_i64 => {
247 format!("{name}: val.{name}.map(|v| std::time::Duration::from_millis(v as u64)).unwrap_or_default()")
248 }
249 TypeRef::Duration => {
250 format!("{name}: val.{name}.map(std::time::Duration::from_millis).unwrap_or_default()")
251 }
252 TypeRef::Path => {
253 format!("{name}: val.{name}.map(Into::into).unwrap_or_default()")
254 }
255 TypeRef::Optional(inner) if matches!(inner.as_ref(), TypeRef::Path) => {
256 format!("{name}: val.{name}.map(|s| std::path::PathBuf::from(s))")
258 }
259 TypeRef::Optional(_) => {
260 format!("{name}: val.{name}.map(Some)")
263 }
264 TypeRef::Char => {
266 format!("{name}: val.{name}.and_then(|s| s.chars().next()).unwrap_or('*')")
267 }
268 TypeRef::Vec(inner) => match inner.as_ref() {
269 TypeRef::Json => {
270 format!(
271 "{name}: val.{name}.map(|v| v.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect()).unwrap_or_default()"
272 )
273 }
274 TypeRef::Named(_) => {
275 format!("{name}: val.{name}.map(|v| v.into_iter().map(Into::into).collect()).unwrap_or_default()")
276 }
277 TypeRef::Primitive(p) if config.cast_large_ints_to_i64 && needs_i64_cast(p) => {
278 let core_ty = core_prim_str(p);
279 format!(
280 "{name}: val.{name}.map(|v| v.into_iter().map(|x| x as {core_ty}).collect()).unwrap_or_default()"
281 )
282 }
283 _ => format!("{name}: val.{name}.unwrap_or_default()"),
284 },
285 TypeRef::Map(k, v) if matches!(v.as_ref(), TypeRef::Json) => {
286 let k_is_json = matches!(k.as_ref(), TypeRef::Json);
288 let k_expr = if k_is_json {
289 "serde_json::from_str(&k).unwrap_or_default()"
290 } else {
291 "k"
292 };
293 format!(
294 "{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()"
295 )
296 }
297 TypeRef::Map(k, _v) if matches!(k.as_ref(), TypeRef::Json) => {
298 format!(
300 "{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (serde_json::from_str(&k).unwrap_or_default(), v)).collect()"
301 )
302 }
303 TypeRef::Map(k, v) => {
304 let has_named_val = matches!(v.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n));
306 let val_is_string_enum = matches!(v.as_ref(), TypeRef::Named(n)
307 if config.enum_string_names.as_ref().is_some_and(|names| names.contains(n)));
308 if val_is_string_enum {
309 format!(
310 "{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (k, serde_json::from_str(&v).unwrap_or_default())).collect()"
311 )
312 } else if has_named_val {
313 format!("{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (k, v.into())).collect()")
314 } else if matches!(k.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n)) {
315 format!("{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (k.into(), v)).collect()")
316 } else {
317 format!("{name}: val.{name}.unwrap_or_default().into_iter().collect()")
318 }
319 }
320 _ => {
321 format!("{name}: val.{name}.unwrap_or_default()")
323 }
324 }
325}
326
327pub fn field_conversion_to_core(name: &str, ty: &TypeRef, optional: bool) -> String {
329 match ty {
330 TypeRef::Primitive(_) | TypeRef::String | TypeRef::Unit => {
332 format!("{name}: val.{name}")
333 }
334 TypeRef::Bytes => {
336 if optional {
337 format!("{name}: val.{name}.map(Into::into)")
338 } else {
339 format!("{name}: val.{name}.into()")
340 }
341 }
342 TypeRef::Json => {
344 if optional {
345 format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok())")
346 } else {
347 format!("{name}: serde_json::from_str(&val.{name}).unwrap_or_default()")
348 }
349 }
350 TypeRef::Char => {
352 if optional {
353 format!("{name}: val.{name}.and_then(|s| s.chars().next())")
354 } else {
355 format!("{name}: val.{name}.chars().next().unwrap_or('*')")
356 }
357 }
358 TypeRef::Duration => {
360 if optional {
361 format!("{name}: val.{name}.map(std::time::Duration::from_millis)")
362 } else {
363 format!("{name}: std::time::Duration::from_millis(val.{name})")
364 }
365 }
366 TypeRef::Path => {
368 if optional {
369 format!("{name}: val.{name}.map(Into::into)")
370 } else {
371 format!("{name}: val.{name}.into()")
372 }
373 }
374 TypeRef::Named(type_name) if is_tuple_type_name(type_name) => {
377 format!("{name}: val.{name}")
378 }
379 TypeRef::Named(_) => {
380 if optional {
381 format!("{name}: val.{name}.map(Into::into)")
382 } else {
383 format!("{name}: val.{name}.into()")
384 }
385 }
386 TypeRef::Map(k, v) if matches!(v.as_ref(), TypeRef::Json) => {
388 let k_expr = if matches!(k.as_ref(), TypeRef::Json) {
389 "serde_json::from_str(&k).unwrap_or_default()"
390 } else {
391 "k"
392 };
393 if optional {
394 format!(
395 "{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| ({k_expr}, serde_json::from_str(&v).unwrap_or_default())).collect())"
396 )
397 } else {
398 format!(
399 "{name}: val.{name}.into_iter().map(|(k, v)| ({k_expr}, serde_json::from_str(&v).unwrap_or_default())).collect()"
400 )
401 }
402 }
403 TypeRef::Optional(inner) => match inner.as_ref() {
405 TypeRef::Json => format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok())"),
406 TypeRef::Named(_) | TypeRef::Path => format!("{name}: val.{name}.map(Into::into)"),
407 TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Named(_)) => {
408 format!("{name}: val.{name}.map(|v| v.into_iter().map(Into::into).collect())")
409 }
410 _ => format!("{name}: val.{name}"),
411 },
412 TypeRef::Vec(inner) => match inner.as_ref() {
414 TypeRef::Json => {
415 if optional {
416 format!(
417 "{name}: val.{name}.map(|v| v.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect())"
418 )
419 } else {
420 format!("{name}: val.{name}.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect()")
421 }
422 }
423 TypeRef::Named(type_name) if is_tuple_type_name(type_name) => {
425 format!("{name}: val.{name}")
426 }
427 TypeRef::Named(_) => {
428 if optional {
429 format!("{name}: val.{name}.map(|v| v.into_iter().map(Into::into).collect())")
430 } else {
431 format!("{name}: val.{name}.into_iter().map(Into::into).collect()")
432 }
433 }
434 _ => format!("{name}: val.{name}"),
435 },
436 TypeRef::Map(k, v) => {
439 let has_named_key = matches!(k.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n));
440 let has_named_val = matches!(v.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n));
441 let has_json_val = matches!(v.as_ref(), TypeRef::Json);
442 let has_json_key = matches!(k.as_ref(), TypeRef::Json);
443 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)));
445 let has_vec_json_val = matches!(v.as_ref(), TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Json));
447 if has_json_val || has_json_key || has_named_key || has_named_val || has_vec_named_val || has_vec_json_val {
448 let k_expr = if has_json_key {
449 "serde_json::from_str(&k).unwrap_or(serde_json::Value::String(k))"
450 } else if has_named_key {
451 "k.into()"
452 } else {
453 "k"
454 };
455 let v_expr = if has_json_val {
456 "serde_json::from_str(&v).unwrap_or(serde_json::Value::String(v))"
457 } else if has_named_val {
458 "v.into()"
459 } else if has_vec_named_val {
460 "v.into_iter().map(Into::into).collect()"
461 } else if has_vec_json_val {
462 "v.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect()"
463 } else {
464 "v"
465 };
466 if optional {
467 format!("{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| ({k_expr}, {v_expr})).collect())")
468 } else {
469 format!("{name}: val.{name}.into_iter().map(|(k, v)| ({k_expr}, {v_expr})).collect()")
470 }
471 } else {
472 if optional {
474 format!("{name}: val.{name}.map(|m| m.into_iter().collect())")
475 } else {
476 format!("{name}: val.{name}.into_iter().collect()")
477 }
478 }
479 }
480 }
481}
482
483pub fn field_conversion_to_core_cfg(name: &str, ty: &TypeRef, optional: bool, config: &ConversionConfig) -> String {
485 if optional && matches!(ty, TypeRef::Optional(_)) {
489 let inner_expr = field_conversion_to_core_cfg(name, ty, false, config);
492 if let Some(expr) = inner_expr.strip_prefix(&format!("{name}: ")) {
494 return format!("{name}: ({expr}).map(Some)");
495 }
496 return inner_expr;
497 }
498
499 if config.map_uses_jsvalue {
501 let is_nested_vec = matches!(ty, TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Vec(_)));
502 let is_vec_json = matches!(ty, TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Json));
503 let is_map = matches!(ty, TypeRef::Map(_, _));
504 if is_nested_vec || is_map || is_vec_json {
505 if optional {
506 return format!(
507 "{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::from_value(v.clone()).ok())"
508 );
509 }
510 return format!("{name}: serde_wasm_bindgen::from_value(val.{name}.clone()).unwrap_or_default()");
511 }
512 if let TypeRef::Optional(inner) = ty {
513 let is_inner_nested = matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Vec(_)));
514 let is_inner_vec_json = matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Json));
515 let is_inner_map = matches!(inner.as_ref(), TypeRef::Map(_, _));
516 if is_inner_nested || is_inner_map || is_inner_vec_json {
517 return format!(
518 "{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::from_value(v.clone()).ok())"
519 );
520 }
521 }
522 }
523
524 if config.vec_named_to_string {
528 if let TypeRef::Vec(inner) = ty {
529 if matches!(inner.as_ref(), TypeRef::Named(_)) {
530 if optional {
531 return format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok())");
532 }
533 return format!("{name}: serde_json::from_str(&val.{name}).unwrap_or_default()");
534 }
535 }
536 }
537 if config.json_to_string && matches!(ty, TypeRef::Json) {
539 return format!("{name}: Default::default()");
540 }
541 if config.map_uses_jsvalue && matches!(ty, TypeRef::Json) {
543 if optional {
544 return format!("{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::from_value(v.clone()).ok())");
545 }
546 return format!("{name}: serde_wasm_bindgen::from_value(val.{name}.clone()).unwrap_or_default()");
547 }
548 if !config.cast_large_ints_to_i64
549 && !config.cast_f32_to_f64
550 && !config.json_to_string
551 && !config.vec_named_to_string
552 {
553 return field_conversion_to_core(name, ty, optional);
554 }
555 match ty {
557 TypeRef::Primitive(p) if config.cast_large_ints_to_i64 && needs_i64_cast(p) => {
558 let core_ty = core_prim_str(p);
559 if optional {
560 format!("{name}: val.{name}.map(|v| v as {core_ty})")
561 } else {
562 format!("{name}: val.{name} as {core_ty}")
563 }
564 }
565 TypeRef::Primitive(PrimitiveType::F32) if config.cast_f32_to_f64 => {
567 if optional {
568 format!("{name}: val.{name}.map(|v| v as f32)")
569 } else {
570 format!("{name}: val.{name} as f32")
571 }
572 }
573 TypeRef::Duration if config.cast_large_ints_to_i64 => {
574 if optional {
575 format!("{name}: val.{name}.map(|v| std::time::Duration::from_millis(v as u64))")
576 } else {
577 format!("{name}: std::time::Duration::from_millis(val.{name} as u64)")
578 }
579 }
580 TypeRef::Optional(inner) if matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) => {
581 if let TypeRef::Primitive(p) = inner.as_ref() {
582 let core_ty = core_prim_str(p);
583 format!("{name}: val.{name}.map(|v| v as {core_ty})")
584 } else {
585 field_conversion_to_core(name, ty, optional)
586 }
587 }
588 TypeRef::Vec(inner)
590 if config.cast_large_ints_to_i64
591 && matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
592 {
593 if let TypeRef::Primitive(p) = inner.as_ref() {
594 let core_ty = core_prim_str(p);
595 if optional {
596 format!("{name}: val.{name}.map(|v| v.into_iter().map(|x| x as {core_ty}).collect())")
597 } else {
598 format!("{name}: val.{name}.into_iter().map(|v| v as {core_ty}).collect()")
599 }
600 } else {
601 field_conversion_to_core(name, ty, optional)
602 }
603 }
604 TypeRef::Map(_k, v)
606 if config.cast_large_ints_to_i64 && matches!(v.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
607 {
608 if let TypeRef::Primitive(p) = v.as_ref() {
609 let core_ty = core_prim_str(p);
610 if optional {
611 format!("{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| (k, v as {core_ty})).collect())")
612 } else {
613 format!("{name}: val.{name}.into_iter().map(|(k, v)| (k, v as {core_ty})).collect()")
614 }
615 } else {
616 field_conversion_to_core(name, ty, optional)
617 }
618 }
619 TypeRef::Vec(inner)
621 if config.cast_f32_to_f64 && matches!(inner.as_ref(), TypeRef::Primitive(PrimitiveType::F32)) =>
622 {
623 if optional {
624 format!("{name}: val.{name}.map(|v| v.into_iter().map(|x| x as f32).collect())")
625 } else {
626 format!("{name}: val.{name}.into_iter().map(|v| v as f32).collect()")
627 }
628 }
629 TypeRef::Optional(inner)
631 if config.cast_f32_to_f64
632 && matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Primitive(PrimitiveType::F32))) =>
633 {
634 format!("{name}: val.{name}.map(|v| v.into_iter().map(|x| x as f32).collect())")
635 }
636 _ => field_conversion_to_core(name, ty, optional),
638 }
639}
640
641fn apply_core_wrapper_to_core(
644 conversion: &str,
645 name: &str,
646 core_wrapper: &CoreWrapper,
647 vec_inner_core_wrapper: &CoreWrapper,
648 optional: bool,
649) -> String {
650 if *vec_inner_core_wrapper == CoreWrapper::Arc {
652 return conversion
653 .replace(
654 ".map(Into::into).collect()",
655 ".map(|v| std::sync::Arc::new(v.into())).collect()",
656 )
657 .replace(
658 "map(|v| v.into_iter().map(Into::into)",
659 "map(|v| v.into_iter().map(|v| std::sync::Arc::new(v.into()))",
660 );
661 }
662
663 match core_wrapper {
664 CoreWrapper::None => conversion.to_string(),
665 CoreWrapper::Cow => {
666 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::Arc => {
686 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
688 if expr == "Default::default()" {
689 conversion.to_string()
692 } else if optional {
693 format!("{name}: {expr}.map(|v| std::sync::Arc::new(v))")
694 } else {
695 format!("{name}: std::sync::Arc::new({expr})")
696 }
697 } else {
698 conversion.to_string()
699 }
700 }
701 CoreWrapper::Bytes => {
702 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
708 let already_converted_non_opt = expr == format!("val.{name}.into()");
709 let already_converted_opt = expr
710 .strip_prefix(&format!("val.{name}"))
711 .map(|s| s == ".map(Into::into)")
712 .unwrap_or(false);
713 if already_converted_non_opt || already_converted_opt {
714 conversion.to_string()
716 } else if optional {
717 format!("{name}: {expr}.map(Into::into)")
718 } else if expr == format!("val.{name}") {
719 format!("{name}: val.{name}.into()")
720 } else if expr == "Default::default()" {
721 conversion.to_string()
724 } else {
725 format!("{name}: ({expr}).into()")
726 }
727 } else {
728 conversion.to_string()
729 }
730 }
731 CoreWrapper::ArcMutex => {
732 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
734 if optional {
735 format!("{name}: {expr}.map(|v| std::sync::Arc::new(std::sync::Mutex::new(v.into())))")
736 } else if expr == format!("val.{name}") {
737 format!("{name}: std::sync::Arc::new(std::sync::Mutex::new(val.{name}.into()))")
738 } else {
739 format!("{name}: std::sync::Arc::new(std::sync::Mutex::new(({expr}).into()))")
740 }
741 } else {
742 conversion.to_string()
743 }
744 }
745 }
746}