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 let binding_name = config.binding_field_name_owned(&typ.name, &field.name);
83 if !field.optional && matches!(field.ty, TypeRef::Duration) {
84 let cast = if config.cast_large_ints_to_i64 { " as u64" } else { "" };
85 writeln!(
86 out,
87 " if let Some(__v) = val.{binding_name} {{ __result.{} = std::time::Duration::from_millis(__v{cast}); }}",
88 field.name
89 )
90 .ok();
91 continue;
92 }
93 let conversion = if optionalized && !field.optional {
94 gen_optionalized_field_to_core(&field.name, &field.ty, config)
95 } else {
96 field_conversion_to_core_cfg(&field.name, &field.ty, field.optional, config)
97 };
98 let conversion = if binding_name != field.name {
100 conversion.replace(&format!("val.{}", field.name), &format!("val.{binding_name}"))
101 } else {
102 conversion
103 };
104 if let Some(expr) = conversion.strip_prefix(&format!("{}: ", field.name)) {
106 writeln!(out, " __result.{} = {};", field.name, expr).ok();
107 }
108 }
109 writeln!(out, " __result").ok();
110 writeln!(out, " }}").ok();
111 write!(out, "}}").ok();
112 return out;
113 }
114
115 writeln!(out, " Self {{").ok();
116 let optionalized = config.optionalize_defaults && typ.has_default;
117 for field in &typ.fields {
118 if field.cfg.is_some() {
123 continue;
124 }
125 let references_excluded = !config.exclude_types.is_empty()
132 && super::helpers::field_references_excluded_type(&field.ty, config.exclude_types);
133 if references_excluded && typ.has_stripped_cfg_fields {
134 continue;
135 }
136 let conversion = if field.sanitized || references_excluded {
137 format!("{}: Default::default()", field.name)
138 } else if optionalized && !field.optional {
139 gen_optionalized_field_to_core(&field.name, &field.ty, config)
142 } else {
143 field_conversion_to_core_cfg(&field.name, &field.ty, field.optional, config)
144 };
145 let conversion = if let Some(newtype_path) = &field.newtype_wrapper {
151 if let Some(expr) = conversion.strip_prefix(&format!("{}: ", field.name)) {
152 match &field.ty {
155 TypeRef::Optional(_) => format!("{}: ({expr}).map({newtype_path})", field.name),
156 TypeRef::Vec(_) => {
157 format!("{}: ({expr}).into_iter().map({newtype_path}).collect()", field.name)
158 }
159 _ if field.optional => format!("{}: ({expr}).map({newtype_path})", field.name),
160 _ => format!("{}: {newtype_path}({expr})", field.name),
161 }
162 } else {
163 conversion
164 }
165 } else {
166 conversion
167 };
168 let conversion = if field.is_boxed && matches!(&field.ty, TypeRef::Named(_)) {
170 if let Some(expr) = conversion.strip_prefix(&format!("{}: ", field.name)) {
171 if field.optional {
172 format!("{}: {}.map(Box::new)", field.name, expr)
174 } else {
175 format!("{}: Box::new({})", field.name, expr)
176 }
177 } else {
178 conversion
179 }
180 } else {
181 conversion
182 };
183 let is_opaque_arc_field = field.core_wrapper == CoreWrapper::Arc
191 && matches!(&field.ty, TypeRef::Named(n) if config
192 .opaque_types
193 .is_some_and(|opaque| opaque.contains(n.as_str())));
194 let conversion = if is_opaque_arc_field {
195 if field.optional {
196 format!("{}: val.{}.map(|v| v.inner)", field.name, field.name)
197 } else {
198 format!("{}: val.{}.inner", field.name, field.name)
199 }
200 } else {
201 apply_core_wrapper_to_core(
202 &conversion,
203 &field.name,
204 &field.core_wrapper,
205 &field.vec_inner_core_wrapper,
206 field.optional,
207 )
208 };
209 let binding_name = config.binding_field_name_owned(&typ.name, &field.name);
213 let conversion = if binding_name != field.name {
214 conversion.replace(&format!("val.{}", field.name), &format!("val.{binding_name}"))
215 } else {
216 conversion
217 };
218 writeln!(out, " {conversion},").ok();
219 }
220 if typ.has_stripped_cfg_fields {
222 writeln!(out, " ..Default::default()").ok();
223 }
224 writeln!(out, " }}").ok();
225 writeln!(out, " }}").ok();
226 write!(out, "}}").ok();
227 out
228}
229
230pub(super) fn gen_optionalized_field_to_core(name: &str, ty: &TypeRef, config: &ConversionConfig) -> String {
233 match ty {
234 TypeRef::Json => {
235 format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok()).unwrap_or_default()")
236 }
237 TypeRef::Named(_) => {
238 format!("{name}: val.{name}.map(Into::into).unwrap_or_default()")
240 }
241 TypeRef::Primitive(PrimitiveType::F32) if config.cast_f32_to_f64 => {
242 format!("{name}: val.{name}.map(|v| v as f32).unwrap_or(0.0)")
243 }
244 TypeRef::Primitive(PrimitiveType::F32 | PrimitiveType::F64) => {
245 format!("{name}: val.{name}.unwrap_or(0.0)")
246 }
247 TypeRef::Primitive(p) if config.cast_large_ints_to_i64 && needs_i64_cast(p) => {
248 let core_ty = core_prim_str(p);
249 format!("{name}: val.{name}.map(|v| v as {core_ty}).unwrap_or_default()")
250 }
251 TypeRef::Optional(inner)
252 if config.cast_large_ints_to_i64
253 && matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
254 {
255 if let TypeRef::Primitive(p) = inner.as_ref() {
256 let core_ty = core_prim_str(p);
257 format!("{name}: val.{name}.map(|v| v as {core_ty})")
258 } else {
259 field_conversion_to_core(name, ty, false)
260 }
261 }
262 TypeRef::Duration if config.cast_large_ints_to_i64 => {
263 format!("{name}: val.{name}.map(|v| std::time::Duration::from_millis(v as u64)).unwrap_or_default()")
264 }
265 TypeRef::Duration => {
266 format!("{name}: val.{name}.map(std::time::Duration::from_millis).unwrap_or_default()")
267 }
268 TypeRef::Path => {
269 format!("{name}: val.{name}.map(Into::into).unwrap_or_default()")
270 }
271 TypeRef::Optional(inner) if matches!(inner.as_ref(), TypeRef::Path) => {
272 format!("{name}: val.{name}.map(|s| std::path::PathBuf::from(s))")
274 }
275 TypeRef::Optional(_) => {
276 format!("{name}: val.{name}.map(Some)")
279 }
280 TypeRef::Char => {
282 format!("{name}: val.{name}.and_then(|s| s.chars().next()).unwrap_or('*')")
283 }
284 TypeRef::Vec(inner) => match inner.as_ref() {
285 TypeRef::Json => {
286 format!(
287 "{name}: val.{name}.map(|v| v.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect()).unwrap_or_default()"
288 )
289 }
290 TypeRef::Named(_) => {
291 format!("{name}: val.{name}.map(|v| v.into_iter().map(Into::into).collect()).unwrap_or_default()")
292 }
293 TypeRef::Primitive(p) if config.cast_large_ints_to_i64 && needs_i64_cast(p) => {
294 let core_ty = core_prim_str(p);
295 format!(
296 "{name}: val.{name}.map(|v| v.into_iter().map(|x| x as {core_ty}).collect()).unwrap_or_default()"
297 )
298 }
299 _ => format!("{name}: val.{name}.unwrap_or_default()"),
300 },
301 TypeRef::Map(k, v) if matches!(v.as_ref(), TypeRef::Json) => {
302 let k_is_json = matches!(k.as_ref(), TypeRef::Json);
304 let k_expr = if k_is_json {
305 "serde_json::from_str(&k).unwrap_or_default()"
306 } else {
307 "k"
308 };
309 format!(
310 "{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()"
311 )
312 }
313 TypeRef::Map(k, _v) if matches!(k.as_ref(), TypeRef::Json) => {
314 format!(
316 "{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (serde_json::from_str(&k).unwrap_or_default(), v)).collect()"
317 )
318 }
319 TypeRef::Map(k, v) => {
320 let has_named_val = matches!(v.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n));
322 let val_is_string_enum = matches!(v.as_ref(), TypeRef::Named(n)
323 if config.enum_string_names.as_ref().is_some_and(|names| names.contains(n)));
324 if val_is_string_enum {
325 format!(
326 "{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (k, serde_json::from_str(&v).unwrap_or_default())).collect()"
327 )
328 } else if has_named_val {
329 format!("{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (k, v.into())).collect()")
330 } else if matches!(k.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n)) {
331 format!("{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (k.into(), v)).collect()")
332 } else {
333 format!("{name}: val.{name}.unwrap_or_default().into_iter().collect()")
334 }
335 }
336 _ => {
337 format!("{name}: val.{name}.unwrap_or_default()")
339 }
340 }
341}
342
343pub fn field_conversion_to_core(name: &str, ty: &TypeRef, optional: bool) -> String {
345 match ty {
346 TypeRef::Primitive(_) | TypeRef::String | TypeRef::Unit => {
348 format!("{name}: val.{name}")
349 }
350 TypeRef::Bytes => {
352 if optional {
353 format!("{name}: val.{name}.map(Into::into)")
354 } else {
355 format!("{name}: val.{name}.into()")
356 }
357 }
358 TypeRef::Json => {
360 if optional {
361 format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok())")
362 } else {
363 format!("{name}: serde_json::from_str(&val.{name}).unwrap_or_default()")
364 }
365 }
366 TypeRef::Char => {
368 if optional {
369 format!("{name}: val.{name}.and_then(|s| s.chars().next())")
370 } else {
371 format!("{name}: val.{name}.chars().next().unwrap_or('*')")
372 }
373 }
374 TypeRef::Duration => {
376 if optional {
377 format!("{name}: val.{name}.map(std::time::Duration::from_millis)")
378 } else {
379 format!("{name}: std::time::Duration::from_millis(val.{name})")
380 }
381 }
382 TypeRef::Path => {
384 if optional {
385 format!("{name}: val.{name}.map(Into::into)")
386 } else {
387 format!("{name}: val.{name}.into()")
388 }
389 }
390 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(Into::into)")
398 } else {
399 format!("{name}: val.{name}.into()")
400 }
401 }
402 TypeRef::Map(k, v) if matches!(v.as_ref(), TypeRef::Json) => {
404 let k_expr = if matches!(k.as_ref(), TypeRef::Json) {
405 "serde_json::from_str(&k).unwrap_or_default()"
406 } else {
407 "k"
408 };
409 if optional {
410 format!(
411 "{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| ({k_expr}, serde_json::from_str(&v).unwrap_or_default())).collect())"
412 )
413 } else {
414 format!(
415 "{name}: val.{name}.into_iter().map(|(k, v)| ({k_expr}, serde_json::from_str(&v).unwrap_or_default())).collect()"
416 )
417 }
418 }
419 TypeRef::Optional(inner) => match inner.as_ref() {
421 TypeRef::Json => format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok())"),
422 TypeRef::Named(_) | TypeRef::Path => format!("{name}: val.{name}.map(Into::into)"),
423 TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Named(_)) => {
424 format!("{name}: val.{name}.map(|v| v.into_iter().map(Into::into).collect())")
425 }
426 _ => format!("{name}: val.{name}"),
427 },
428 TypeRef::Vec(inner) => match inner.as_ref() {
430 TypeRef::Json => {
431 if optional {
432 format!(
433 "{name}: val.{name}.map(|v| v.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect())"
434 )
435 } else {
436 format!("{name}: val.{name}.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect()")
437 }
438 }
439 TypeRef::Named(type_name) if is_tuple_type_name(type_name) => {
441 format!("{name}: val.{name}")
442 }
443 TypeRef::Named(_) => {
444 if optional {
445 format!("{name}: val.{name}.map(|v| v.into_iter().map(Into::into).collect())")
446 } else {
447 format!("{name}: val.{name}.into_iter().map(Into::into).collect()")
448 }
449 }
450 _ => format!("{name}: val.{name}"),
451 },
452 TypeRef::Map(k, v) => {
455 let has_named_key = matches!(k.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n));
456 let has_named_val = matches!(v.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n));
457 let has_json_val = matches!(v.as_ref(), TypeRef::Json);
458 let has_json_key = matches!(k.as_ref(), TypeRef::Json);
459 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)));
461 let has_vec_json_val = matches!(v.as_ref(), TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Json));
463 if has_json_val || has_json_key || has_named_key || has_named_val || has_vec_named_val || has_vec_json_val {
464 let k_expr = if has_json_key {
465 "serde_json::from_str(&k).unwrap_or(serde_json::Value::String(k))"
466 } else if has_named_key {
467 "k.into()"
468 } else {
469 "k"
470 };
471 let v_expr = if has_json_val {
472 "serde_json::from_str(&v).unwrap_or(serde_json::Value::String(v))"
473 } else if has_named_val {
474 "v.into()"
475 } else if has_vec_named_val {
476 "v.into_iter().map(Into::into).collect()"
477 } else if has_vec_json_val {
478 "v.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect()"
479 } else {
480 "v"
481 };
482 if optional {
483 format!("{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| ({k_expr}, {v_expr})).collect())")
484 } else {
485 format!("{name}: val.{name}.into_iter().map(|(k, v)| ({k_expr}, {v_expr})).collect()")
486 }
487 } else {
488 if optional {
490 format!("{name}: val.{name}.map(|m| m.into_iter().collect())")
491 } else {
492 format!("{name}: val.{name}.into_iter().collect()")
493 }
494 }
495 }
496 }
497}
498
499pub fn field_conversion_to_core_cfg(name: &str, ty: &TypeRef, optional: bool, config: &ConversionConfig) -> String {
501 if optional && matches!(ty, TypeRef::Optional(_)) {
505 let inner_expr = field_conversion_to_core_cfg(name, ty, false, config);
508 if let Some(expr) = inner_expr.strip_prefix(&format!("{name}: ")) {
510 return format!("{name}: ({expr}).map(Some)");
511 }
512 return inner_expr;
513 }
514
515 if config.map_uses_jsvalue {
517 let is_nested_vec = matches!(ty, TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Vec(_)));
518 let is_vec_json = matches!(ty, TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Json));
519 let is_map = matches!(ty, TypeRef::Map(_, _));
520 if is_nested_vec || is_map || is_vec_json {
521 if optional {
522 return format!(
523 "{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::from_value(v.clone()).ok())"
524 );
525 }
526 return format!("{name}: serde_wasm_bindgen::from_value(val.{name}.clone()).unwrap_or_default()");
527 }
528 if let TypeRef::Optional(inner) = ty {
529 let is_inner_nested = matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Vec(_)));
530 let is_inner_vec_json = matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Json));
531 let is_inner_map = matches!(inner.as_ref(), TypeRef::Map(_, _));
532 if is_inner_nested || is_inner_map || is_inner_vec_json {
533 return format!(
534 "{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::from_value(v.clone()).ok())"
535 );
536 }
537 }
538 }
539
540 if config.vec_named_to_string {
544 if let TypeRef::Vec(inner) = ty {
545 if matches!(inner.as_ref(), TypeRef::Named(_)) {
546 if optional {
547 return format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok())");
548 }
549 return format!("{name}: serde_json::from_str(&val.{name}).unwrap_or_default()");
550 }
551 }
552 }
553 if config.json_to_string && matches!(ty, TypeRef::Json) {
555 return format!("{name}: Default::default()");
556 }
557 if config.map_uses_jsvalue && matches!(ty, TypeRef::Json) {
559 if optional {
560 return format!("{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::from_value(v.clone()).ok())");
561 }
562 return format!("{name}: serde_wasm_bindgen::from_value(val.{name}.clone()).unwrap_or_default()");
563 }
564 if !config.cast_large_ints_to_i64
565 && !config.cast_f32_to_f64
566 && !config.json_to_string
567 && !config.vec_named_to_string
568 {
569 return field_conversion_to_core(name, ty, optional);
570 }
571 match ty {
573 TypeRef::Primitive(p) if config.cast_large_ints_to_i64 && needs_i64_cast(p) => {
574 let core_ty = core_prim_str(p);
575 if optional {
576 format!("{name}: val.{name}.map(|v| v as {core_ty})")
577 } else {
578 format!("{name}: val.{name} as {core_ty}")
579 }
580 }
581 TypeRef::Primitive(PrimitiveType::F32) if config.cast_f32_to_f64 => {
583 if optional {
584 format!("{name}: val.{name}.map(|v| v as f32)")
585 } else {
586 format!("{name}: val.{name} as f32")
587 }
588 }
589 TypeRef::Duration if config.cast_large_ints_to_i64 => {
590 if optional {
591 format!("{name}: val.{name}.map(|v| std::time::Duration::from_millis(v as u64))")
592 } else {
593 format!("{name}: std::time::Duration::from_millis(val.{name} as u64)")
594 }
595 }
596 TypeRef::Optional(inner) if matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) => {
597 if let TypeRef::Primitive(p) = inner.as_ref() {
598 let core_ty = core_prim_str(p);
599 format!("{name}: val.{name}.map(|v| v as {core_ty})")
600 } else {
601 field_conversion_to_core(name, ty, optional)
602 }
603 }
604 TypeRef::Vec(inner)
606 if config.cast_large_ints_to_i64
607 && matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
608 {
609 if let TypeRef::Primitive(p) = inner.as_ref() {
610 let core_ty = core_prim_str(p);
611 if optional {
612 format!("{name}: val.{name}.map(|v| v.into_iter().map(|x| x as {core_ty}).collect())")
613 } else {
614 format!("{name}: val.{name}.into_iter().map(|v| v as {core_ty}).collect()")
615 }
616 } else {
617 field_conversion_to_core(name, ty, optional)
618 }
619 }
620 TypeRef::Map(_k, v)
622 if config.cast_large_ints_to_i64 && matches!(v.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
623 {
624 if let TypeRef::Primitive(p) = v.as_ref() {
625 let core_ty = core_prim_str(p);
626 if optional {
627 format!("{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| (k, v as {core_ty})).collect())")
628 } else {
629 format!("{name}: val.{name}.into_iter().map(|(k, v)| (k, v as {core_ty})).collect()")
630 }
631 } else {
632 field_conversion_to_core(name, ty, optional)
633 }
634 }
635 TypeRef::Vec(inner)
637 if config.cast_f32_to_f64 && matches!(inner.as_ref(), TypeRef::Primitive(PrimitiveType::F32)) =>
638 {
639 if optional {
640 format!("{name}: val.{name}.map(|v| v.into_iter().map(|x| x as f32).collect())")
641 } else {
642 format!("{name}: val.{name}.into_iter().map(|v| v as f32).collect()")
643 }
644 }
645 TypeRef::Optional(inner)
647 if config.cast_f32_to_f64
648 && matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Primitive(PrimitiveType::F32))) =>
649 {
650 format!("{name}: val.{name}.map(|v| v.into_iter().map(|x| x as f32).collect())")
651 }
652 _ => field_conversion_to_core(name, ty, optional),
654 }
655}
656
657fn apply_core_wrapper_to_core(
660 conversion: &str,
661 name: &str,
662 core_wrapper: &CoreWrapper,
663 vec_inner_core_wrapper: &CoreWrapper,
664 optional: bool,
665) -> String {
666 if *vec_inner_core_wrapper == CoreWrapper::Arc {
668 return conversion
669 .replace(
670 ".map(Into::into).collect()",
671 ".map(|v| std::sync::Arc::new(v.into())).collect()",
672 )
673 .replace(
674 "map(|v| v.into_iter().map(Into::into)",
675 "map(|v| v.into_iter().map(|v| std::sync::Arc::new(v.into()))",
676 );
677 }
678
679 match core_wrapper {
680 CoreWrapper::None => conversion.to_string(),
681 CoreWrapper::Cow => {
682 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
686 if optional {
687 format!("{name}: {expr}.map(Into::into)")
688 } else if expr == format!("val.{name}") {
689 format!("{name}: val.{name}.into()")
690 } else if expr == "Default::default()" {
691 conversion.to_string()
694 } else {
695 format!("{name}: ({expr}).into()")
696 }
697 } else {
698 conversion.to_string()
699 }
700 }
701 CoreWrapper::Arc => {
702 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
704 if expr == "Default::default()" {
705 conversion.to_string()
708 } else if optional {
709 format!("{name}: {expr}.map(|v| std::sync::Arc::new(v))")
710 } else {
711 format!("{name}: std::sync::Arc::new({expr})")
712 }
713 } else {
714 conversion.to_string()
715 }
716 }
717 CoreWrapper::Bytes => {
718 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
724 let already_converted_non_opt = expr == format!("val.{name}.into()");
725 let already_converted_opt = expr
726 .strip_prefix(&format!("val.{name}"))
727 .map(|s| s == ".map(Into::into)")
728 .unwrap_or(false);
729 if already_converted_non_opt || already_converted_opt {
730 conversion.to_string()
732 } else if optional {
733 format!("{name}: {expr}.map(Into::into)")
734 } else if expr == format!("val.{name}") {
735 format!("{name}: val.{name}.into()")
736 } else if expr == "Default::default()" {
737 conversion.to_string()
740 } else {
741 format!("{name}: ({expr}).into()")
742 }
743 } else {
744 conversion.to_string()
745 }
746 }
747 CoreWrapper::ArcMutex => {
748 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
750 if optional {
751 format!("{name}: {expr}.map(|v| std::sync::Arc::new(std::sync::Mutex::new(v.into())))")
752 } else if expr == format!("val.{name}") {
753 format!("{name}: std::sync::Arc::new(std::sync::Mutex::new(val.{name}.into()))")
754 } else {
755 format!("{name}: std::sync::Arc::new(std::sync::Mutex::new(({expr}).into()))")
756 }
757 } else {
758 conversion.to_string()
759 }
760 }
761 }
762}