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_remapped, 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_remapped(typ, core_import, config.source_crate_remaps);
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, "#[allow(clippy::redundant_closure, clippy::useless_conversion)]").ok();
34 writeln!(out, "impl From<{binding_name}> for {core_path} {{").ok();
35 writeln!(out, " fn from(val: {binding_name}) -> Self {{").ok();
36
37 if is_newtype(typ) {
39 let field = &typ.fields[0];
40 let inner_expr = match &field.ty {
41 TypeRef::Named(_) => "val._0.into()".to_string(),
42 TypeRef::Path => "val._0.into()".to_string(),
43 TypeRef::Duration => "std::time::Duration::from_millis(val._0)".to_string(),
44 _ => "val._0".to_string(),
45 };
46 writeln!(out, " Self({inner_expr})").ok();
47 writeln!(out, " }}").ok();
48 write!(out, "}}").ok();
49 return out;
50 }
51
52 let has_optionalized_duration = config.option_duration_on_defaults
57 && typ.has_default
58 && typ
59 .fields
60 .iter()
61 .any(|f| !f.optional && matches!(f.ty, TypeRef::Duration));
62
63 if has_optionalized_duration {
64 writeln!(out, " let mut __result = {core_path}::default();").ok();
66 let optionalized = config.optionalize_defaults && typ.has_default;
67 for field in &typ.fields {
68 if field.cfg.is_some() {
70 continue;
71 }
72 if field.sanitized {
73 continue;
75 }
76 if !config.exclude_types.is_empty()
78 && super::helpers::field_references_excluded_type(&field.ty, config.exclude_types)
79 {
80 continue;
81 }
82 let binding_name = config.binding_field_name_owned(&typ.name, &field.name);
84 if !field.optional && matches!(field.ty, TypeRef::Duration) {
85 let cast = if config.cast_large_ints_to_i64 { " as u64" } else { "" };
86 writeln!(
87 out,
88 " if let Some(__v) = val.{binding_name} {{ __result.{} = std::time::Duration::from_millis(__v{cast}); }}",
89 field.name
90 )
91 .ok();
92 continue;
93 }
94 let conversion = if optionalized && !field.optional {
95 gen_optionalized_field_to_core(&field.name, &field.ty, config, false)
96 } else {
97 field_conversion_to_core_cfg(&field.name, &field.ty, field.optional, config)
98 };
99 let conversion = if binding_name != field.name {
101 conversion.replace(&format!("val.{}", field.name), &format!("val.{binding_name}"))
102 } else {
103 conversion
104 };
105 if let Some(expr) = conversion.strip_prefix(&format!("{}: ", field.name)) {
107 writeln!(out, " __result.{} = {};", field.name, expr).ok();
108 }
109 }
110 writeln!(out, " __result").ok();
111 writeln!(out, " }}").ok();
112 write!(out, "}}").ok();
113 return out;
114 }
115
116 writeln!(out, " Self {{").ok();
117 let optionalized = config.optionalize_defaults && typ.has_default;
118 for field in &typ.fields {
119 if field.cfg.is_some() {
124 continue;
125 }
126 let references_excluded = !config.exclude_types.is_empty()
133 && super::helpers::field_references_excluded_type(&field.ty, config.exclude_types);
134 if references_excluded && typ.has_stripped_cfg_fields {
135 continue;
136 }
137 let conversion = if field.sanitized || references_excluded {
138 format!("{}: Default::default()", field.name)
139 } else if optionalized && !field.optional {
140 gen_optionalized_field_to_core(&field.name, &field.ty, config, false)
143 } else {
144 field_conversion_to_core_cfg(&field.name, &field.ty, field.optional, config)
145 };
146 let conversion = if let Some(newtype_path) = &field.newtype_wrapper {
152 if let Some(expr) = conversion.strip_prefix(&format!("{}: ", field.name)) {
153 match &field.ty {
156 TypeRef::Optional(_) => format!("{}: ({expr}).map({newtype_path})", field.name),
157 TypeRef::Vec(_) => {
158 format!("{}: ({expr}).into_iter().map({newtype_path}).collect()", field.name)
159 }
160 _ if field.optional => format!("{}: ({expr}).map({newtype_path})", field.name),
161 _ => format!("{}: {newtype_path}({expr})", field.name),
162 }
163 } else {
164 conversion
165 }
166 } else {
167 conversion
168 };
169 let conversion = if field.is_boxed && matches!(&field.ty, TypeRef::Named(_)) {
171 if let Some(expr) = conversion.strip_prefix(&format!("{}: ", field.name)) {
172 if field.optional {
173 format!("{}: {}.map(Box::new)", field.name, expr)
175 } else {
176 format!("{}: Box::new({})", field.name, expr)
177 }
178 } else {
179 conversion
180 }
181 } else {
182 conversion
183 };
184 let is_opaque_arc_field = field.core_wrapper == CoreWrapper::Arc
192 && matches!(&field.ty, TypeRef::Named(n) if config
193 .opaque_types
194 .is_some_and(|opaque| opaque.contains(n.as_str())));
195 let conversion = if is_opaque_arc_field {
196 if field.optional {
197 format!("{}: val.{}.map(|v| v.inner)", field.name, field.name)
198 } else {
199 format!("{}: val.{}.inner", field.name, field.name)
200 }
201 } else {
202 apply_core_wrapper_to_core(
203 &conversion,
204 &field.name,
205 &field.core_wrapper,
206 &field.vec_inner_core_wrapper,
207 field.optional,
208 )
209 };
210 let binding_name = config.binding_field_name_owned(&typ.name, &field.name);
214 let conversion = if binding_name != field.name {
215 conversion.replace(&format!("val.{}", field.name), &format!("val.{binding_name}"))
216 } else {
217 conversion
218 };
219 writeln!(out, " {conversion},").ok();
220 }
221 if typ.has_stripped_cfg_fields {
223 writeln!(out, " ..Default::default()").ok();
224 }
225 writeln!(out, " }}").ok();
226 writeln!(out, " }}").ok();
227 write!(out, "}}").ok();
228 out
229}
230
231pub(super) fn gen_optionalized_field_to_core(
236 name: &str,
237 ty: &TypeRef,
238 config: &ConversionConfig,
239 field_is_ir_optional: bool,
240) -> String {
241 match ty {
242 TypeRef::Json => {
243 format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok()).unwrap_or_default()")
244 }
245 TypeRef::Named(_) => {
246 format!("{name}: val.{name}.map(Into::into).unwrap_or_default()")
248 }
249 TypeRef::Primitive(PrimitiveType::F32) if config.cast_f32_to_f64 => {
250 format!("{name}: val.{name}.map(|v| v as f32).unwrap_or(0.0)")
251 }
252 TypeRef::Primitive(PrimitiveType::F32 | PrimitiveType::F64) => {
253 format!("{name}: val.{name}.unwrap_or(0.0)")
254 }
255 TypeRef::Primitive(p) if config.cast_large_ints_to_i64 && needs_i64_cast(p) => {
256 let core_ty = core_prim_str(p);
257 format!("{name}: val.{name}.map(|v| v as {core_ty}).unwrap_or_default()")
258 }
259 TypeRef::Optional(inner)
260 if config.cast_large_ints_to_i64
261 && matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
262 {
263 if let TypeRef::Primitive(p) = inner.as_ref() {
264 let core_ty = core_prim_str(p);
265 format!("{name}: val.{name}.map(|v| v as {core_ty})")
266 } else {
267 field_conversion_to_core(name, ty, false)
268 }
269 }
270 TypeRef::Duration if config.cast_large_ints_to_i64 => {
271 format!("{name}: val.{name}.map(|v| std::time::Duration::from_millis(v as u64)).unwrap_or_default()")
272 }
273 TypeRef::Duration => {
274 format!("{name}: val.{name}.map(std::time::Duration::from_millis).unwrap_or_default()")
275 }
276 TypeRef::Path => {
277 format!("{name}: val.{name}.map(Into::into).unwrap_or_default()")
278 }
279 TypeRef::Optional(inner) if matches!(inner.as_ref(), TypeRef::Path) => {
280 format!("{name}: val.{name}.map(|s| std::path::PathBuf::from(s))")
282 }
283 TypeRef::Optional(_) => {
284 format!("{name}: val.{name}.map(Some)")
287 }
288 TypeRef::Char => {
290 format!("{name}: val.{name}.and_then(|s| s.chars().next()).unwrap_or('*')")
291 }
292 TypeRef::Vec(inner) => match inner.as_ref() {
293 TypeRef::Json => {
294 format!(
295 "{name}: val.{name}.map(|v| v.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect()).unwrap_or_default()"
296 )
297 }
298 TypeRef::Named(_) => {
299 format!("{name}: val.{name}.map(|v| v.into_iter().map(Into::into).collect()).unwrap_or_default()")
300 }
301 TypeRef::Primitive(p) if config.cast_large_ints_to_i64 && needs_i64_cast(p) => {
302 let core_ty = core_prim_str(p);
303 format!(
304 "{name}: val.{name}.map(|v| v.into_iter().map(|x| x as {core_ty}).collect()).unwrap_or_default()"
305 )
306 }
307 _ => format!("{name}: val.{name}.unwrap_or_default()"),
308 },
309 TypeRef::Map(k, v) if matches!(v.as_ref(), TypeRef::Json) => {
310 let k_is_json = matches!(k.as_ref(), TypeRef::Json);
314 let k_expr = if k_is_json {
315 "serde_json::from_str(&k).unwrap_or_default()"
316 } else {
317 "k.into()"
318 };
319 format!(
320 "{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()"
321 )
322 }
323 TypeRef::Map(k, _v) if matches!(k.as_ref(), TypeRef::Json) => {
324 format!(
326 "{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (serde_json::from_str(&k).unwrap_or_default(), v)).collect()"
327 )
328 }
329 TypeRef::Map(k, v) => {
330 let has_named_val = matches!(v.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n));
332 let has_named_key = matches!(k.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n));
333 let val_is_string_enum = matches!(v.as_ref(), TypeRef::Named(n)
334 if config.enum_string_names.as_ref().is_some_and(|names| names.contains(n)));
335 if field_is_ir_optional {
336 if val_is_string_enum {
338 format!(
339 "{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| (k, serde_json::from_str(&v).unwrap_or_default())).collect())"
340 )
341 } else if has_named_val {
342 format!("{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| (k, v.into())).collect())")
343 } else if has_named_key {
344 format!("{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| (k.into(), v)).collect())")
345 } else {
346 format!("{name}: val.{name}.map(|m| m.into_iter().collect())")
347 }
348 } else if val_is_string_enum {
349 format!(
350 "{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (k, serde_json::from_str(&v).unwrap_or_default())).collect()"
351 )
352 } else if has_named_val {
353 format!("{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (k, v.into())).collect()")
354 } else if has_named_key {
355 format!("{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (k.into(), v)).collect()")
356 } else {
357 format!("{name}: val.{name}.unwrap_or_default().into_iter().collect()")
358 }
359 }
360 _ => {
361 format!("{name}: val.{name}.unwrap_or_default()")
363 }
364 }
365}
366
367pub fn field_conversion_to_core(name: &str, ty: &TypeRef, optional: bool) -> String {
369 match ty {
370 TypeRef::Primitive(_) | TypeRef::String | TypeRef::Unit => {
372 format!("{name}: val.{name}")
373 }
374 TypeRef::Bytes => {
376 if optional {
377 format!("{name}: val.{name}.map(Into::into)")
378 } else {
379 format!("{name}: val.{name}.into()")
380 }
381 }
382 TypeRef::Json => {
384 if optional {
385 format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok())")
386 } else {
387 format!("{name}: serde_json::from_str(&val.{name}).unwrap_or_default()")
388 }
389 }
390 TypeRef::Char => {
392 if optional {
393 format!("{name}: val.{name}.and_then(|s| s.chars().next())")
394 } else {
395 format!("{name}: val.{name}.chars().next().unwrap_or('*')")
396 }
397 }
398 TypeRef::Duration => {
400 if optional {
401 format!("{name}: val.{name}.map(std::time::Duration::from_millis)")
402 } else {
403 format!("{name}: std::time::Duration::from_millis(val.{name})")
404 }
405 }
406 TypeRef::Path => {
408 if optional {
409 format!("{name}: val.{name}.map(Into::into)")
410 } else {
411 format!("{name}: val.{name}.into()")
412 }
413 }
414 TypeRef::Named(type_name) if is_tuple_type_name(type_name) => {
417 format!("{name}: val.{name}")
418 }
419 TypeRef::Named(_) => {
420 if optional {
421 format!("{name}: val.{name}.map(Into::into)")
422 } else {
423 format!("{name}: val.{name}.into()")
424 }
425 }
426 TypeRef::Map(k, v) if matches!(v.as_ref(), TypeRef::Json) => {
430 let k_expr = if matches!(k.as_ref(), TypeRef::Json) {
431 "serde_json::from_str(&k).unwrap_or_default()"
432 } else {
433 "k.into()"
434 };
435 if optional {
436 format!(
437 "{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| ({k_expr}, serde_json::from_str(&v).unwrap_or_default())).collect())"
438 )
439 } else {
440 format!(
441 "{name}: val.{name}.into_iter().map(|(k, v)| ({k_expr}, serde_json::from_str(&v).unwrap_or_default())).collect()"
442 )
443 }
444 }
445 TypeRef::Optional(inner) => match inner.as_ref() {
447 TypeRef::Json => format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok())"),
448 TypeRef::Named(_) | TypeRef::Path => format!("{name}: val.{name}.map(Into::into)"),
449 TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Named(_)) => {
450 format!("{name}: val.{name}.map(|v| v.into_iter().map(Into::into).collect())")
451 }
452 _ => format!("{name}: val.{name}"),
453 },
454 TypeRef::Vec(inner) => match inner.as_ref() {
456 TypeRef::Json => {
457 if optional {
458 format!(
459 "{name}: val.{name}.map(|v| v.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect())"
460 )
461 } else {
462 format!("{name}: val.{name}.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect()")
463 }
464 }
465 TypeRef::Named(type_name) if is_tuple_type_name(type_name) => {
467 format!("{name}: val.{name}")
468 }
469 TypeRef::Named(_) => {
470 if optional {
471 format!("{name}: val.{name}.map(|v| v.into_iter().map(Into::into).collect())")
472 } else {
473 format!("{name}: val.{name}.into_iter().map(Into::into).collect()")
474 }
475 }
476 _ => format!("{name}: val.{name}"),
477 },
478 TypeRef::Map(k, v) => {
481 let has_named_key = matches!(k.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n));
482 let has_named_val = matches!(v.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n));
483 let has_json_val = matches!(v.as_ref(), TypeRef::Json);
484 let has_json_key = matches!(k.as_ref(), TypeRef::Json);
485 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)));
487 let has_vec_json_val = matches!(v.as_ref(), TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Json));
489 if has_json_val || has_json_key || has_named_key || has_named_val || has_vec_named_val || has_vec_json_val {
490 let k_expr = if has_json_key {
491 "serde_json::from_str(&k).unwrap_or(serde_json::Value::String(k))"
492 } else if has_named_key {
493 "k.into()"
494 } else {
495 "k"
496 };
497 let v_expr = if has_json_val {
498 "serde_json::from_str(&v).unwrap_or(serde_json::Value::String(v))"
499 } else if has_named_val {
500 "v.into()"
501 } else if has_vec_named_val {
502 "v.into_iter().map(Into::into).collect()"
503 } else if has_vec_json_val {
504 "v.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect()"
505 } else {
506 "v"
507 };
508 if optional {
509 format!("{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| ({k_expr}, {v_expr})).collect())")
510 } else {
511 format!("{name}: val.{name}.into_iter().map(|(k, v)| ({k_expr}, {v_expr})).collect()")
512 }
513 } else {
514 if optional {
518 if has_named_val {
519 format!("{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| (k, v.into())).collect())")
520 } else {
521 format!("{name}: val.{name}.map(|m| m.into_iter().collect())")
522 }
523 } else {
524 format!("{name}: val.{name}.into_iter().collect()")
525 }
526 }
527 }
528 }
529}
530
531pub fn field_conversion_to_core_cfg(name: &str, ty: &TypeRef, optional: bool, config: &ConversionConfig) -> String {
533 if optional && matches!(ty, TypeRef::Optional(_)) {
537 let inner_expr = field_conversion_to_core_cfg(name, ty, false, config);
540 if let Some(expr) = inner_expr.strip_prefix(&format!("{name}: ")) {
542 return format!("{name}: ({expr}).map(Some)");
543 }
544 return inner_expr;
545 }
546
547 if config.map_uses_jsvalue {
549 let is_nested_vec = matches!(ty, TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Vec(_)));
550 let is_vec_json = matches!(ty, TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Json));
551 let is_map = matches!(ty, TypeRef::Map(_, _));
552 if is_nested_vec || is_map || is_vec_json {
553 if optional {
554 return format!(
555 "{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::from_value(v.clone()).ok())"
556 );
557 }
558 return format!("{name}: serde_wasm_bindgen::from_value(val.{name}.clone()).unwrap_or_default()");
559 }
560 if let TypeRef::Optional(inner) = ty {
561 let is_inner_nested = matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Vec(_)));
562 let is_inner_vec_json = matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Json));
563 let is_inner_map = matches!(inner.as_ref(), TypeRef::Map(_, _));
564 if is_inner_nested || is_inner_map || is_inner_vec_json {
565 return format!(
566 "{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::from_value(v.clone()).ok())"
567 );
568 }
569 }
570 }
571
572 if config.vec_named_to_string {
576 if let TypeRef::Vec(inner) = ty {
577 if matches!(inner.as_ref(), TypeRef::Named(_)) {
578 if optional {
579 return format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok())");
580 }
581 return format!("{name}: serde_json::from_str(&val.{name}).unwrap_or_default()");
582 }
583 }
584 }
585 if config.map_as_string && matches!(ty, TypeRef::Map(_, _)) {
587 return format!("{name}: Default::default()");
588 }
589 if config.map_as_string {
590 if let TypeRef::Optional(inner) = ty {
591 if matches!(inner.as_ref(), TypeRef::Map(_, _)) {
592 return format!("{name}: Default::default()");
593 }
594 }
595 }
596 if config.json_to_string && matches!(ty, TypeRef::Json) {
598 return format!("{name}: Default::default()");
599 }
600 if config.map_uses_jsvalue && matches!(ty, TypeRef::Json) {
602 if optional {
603 return format!("{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::from_value(v.clone()).ok())");
604 }
605 return format!("{name}: serde_wasm_bindgen::from_value(val.{name}.clone()).unwrap_or_default()");
606 }
607 if !config.cast_large_ints_to_i64
608 && !config.cast_f32_to_f64
609 && !config.json_to_string
610 && !config.vec_named_to_string
611 && !config.map_as_string
612 {
613 return field_conversion_to_core(name, ty, optional);
614 }
615 match ty {
617 TypeRef::Primitive(p) if config.cast_large_ints_to_i64 && needs_i64_cast(p) => {
618 let core_ty = core_prim_str(p);
619 if optional {
620 format!("{name}: val.{name}.map(|v| v as {core_ty})")
621 } else {
622 format!("{name}: val.{name} as {core_ty}")
623 }
624 }
625 TypeRef::Primitive(PrimitiveType::F32) if config.cast_f32_to_f64 => {
627 if optional {
628 format!("{name}: val.{name}.map(|v| v as f32)")
629 } else {
630 format!("{name}: val.{name} as f32")
631 }
632 }
633 TypeRef::Duration if config.cast_large_ints_to_i64 => {
634 if optional {
635 format!("{name}: val.{name}.map(|v| std::time::Duration::from_millis(v as u64))")
636 } else {
637 format!("{name}: std::time::Duration::from_millis(val.{name} as u64)")
638 }
639 }
640 TypeRef::Optional(inner) if matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) => {
641 if let TypeRef::Primitive(p) = inner.as_ref() {
642 let core_ty = core_prim_str(p);
643 format!("{name}: val.{name}.map(|v| v as {core_ty})")
644 } else {
645 field_conversion_to_core(name, ty, optional)
646 }
647 }
648 TypeRef::Vec(inner)
650 if config.cast_large_ints_to_i64
651 && matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
652 {
653 if let TypeRef::Primitive(p) = inner.as_ref() {
654 let core_ty = core_prim_str(p);
655 if optional {
656 format!("{name}: val.{name}.map(|v| v.into_iter().map(|x| x as {core_ty}).collect())")
657 } else {
658 format!("{name}: val.{name}.into_iter().map(|v| v as {core_ty}).collect()")
659 }
660 } else {
661 field_conversion_to_core(name, ty, optional)
662 }
663 }
664 TypeRef::Map(_k, v)
666 if config.cast_large_ints_to_i64 && matches!(v.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
667 {
668 if let TypeRef::Primitive(p) = v.as_ref() {
669 let core_ty = core_prim_str(p);
670 if optional {
671 format!("{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| (k, v as {core_ty})).collect())")
672 } else {
673 format!("{name}: val.{name}.into_iter().map(|(k, v)| (k, v as {core_ty})).collect()")
674 }
675 } else {
676 field_conversion_to_core(name, ty, optional)
677 }
678 }
679 TypeRef::Vec(inner)
681 if config.cast_f32_to_f64 && matches!(inner.as_ref(), TypeRef::Primitive(PrimitiveType::F32)) =>
682 {
683 if optional {
684 format!("{name}: val.{name}.map(|v| v.into_iter().map(|x| x as f32).collect())")
685 } else {
686 format!("{name}: val.{name}.into_iter().map(|v| v as f32).collect()")
687 }
688 }
689 TypeRef::Optional(inner)
691 if config.cast_f32_to_f64
692 && matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Primitive(PrimitiveType::F32))) =>
693 {
694 format!("{name}: val.{name}.map(|v| v.into_iter().map(|x| x as f32).collect())")
695 }
696 _ => field_conversion_to_core(name, ty, optional),
698 }
699}
700
701fn apply_core_wrapper_to_core(
704 conversion: &str,
705 name: &str,
706 core_wrapper: &CoreWrapper,
707 vec_inner_core_wrapper: &CoreWrapper,
708 optional: bool,
709) -> String {
710 if *vec_inner_core_wrapper == CoreWrapper::Arc {
712 return conversion
713 .replace(
714 ".map(Into::into).collect()",
715 ".map(|v| std::sync::Arc::new(v.into())).collect()",
716 )
717 .replace(
718 "map(|v| v.into_iter().map(Into::into)",
719 "map(|v| v.into_iter().map(|v| std::sync::Arc::new(v.into()))",
720 );
721 }
722
723 match core_wrapper {
724 CoreWrapper::None => conversion.to_string(),
725 CoreWrapper::Cow => {
726 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
730 if optional {
731 format!("{name}: {expr}.map(Into::into)")
732 } else if expr == format!("val.{name}") {
733 format!("{name}: val.{name}.into()")
734 } else if expr == "Default::default()" {
735 conversion.to_string()
738 } else {
739 format!("{name}: ({expr}).into()")
740 }
741 } else {
742 conversion.to_string()
743 }
744 }
745 CoreWrapper::Arc => {
746 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
748 if expr == "Default::default()" {
749 conversion.to_string()
752 } else if optional {
753 format!("{name}: {expr}.map(|v| std::sync::Arc::new(v))")
754 } else {
755 format!("{name}: std::sync::Arc::new({expr})")
756 }
757 } else {
758 conversion.to_string()
759 }
760 }
761 CoreWrapper::Bytes => {
762 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
768 let already_converted_non_opt = expr == format!("val.{name}.into()");
769 let already_converted_opt = expr
770 .strip_prefix(&format!("val.{name}"))
771 .map(|s| s == ".map(Into::into)")
772 .unwrap_or(false);
773 if already_converted_non_opt || already_converted_opt {
774 conversion.to_string()
776 } else if optional {
777 format!("{name}: {expr}.map(Into::into)")
778 } else if expr == format!("val.{name}") {
779 format!("{name}: val.{name}.into()")
780 } else if expr == "Default::default()" {
781 conversion.to_string()
784 } else {
785 format!("{name}: ({expr}).into()")
786 }
787 } else {
788 conversion.to_string()
789 }
790 }
791 CoreWrapper::ArcMutex => {
792 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
794 if optional {
795 format!("{name}: {expr}.map(|v| std::sync::Arc::new(std::sync::Mutex::new(v.into())))")
796 } else if expr == format!("val.{name}") {
797 format!("{name}: std::sync::Arc::new(std::sync::Mutex::new(val.{name}.into()))")
798 } else {
799 format!("{name}: std::sync::Arc::new(std::sync::Mutex::new(({expr}).into()))")
800 }
801 } else {
802 conversion.to_string()
803 }
804 }
805 }
806}