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 =
138 if field.sanitized || references_excluded || config.force_default_fields.contains(&field.name.as_str()) {
139 format!("{}: Default::default()", field.name)
140 } else if optionalized && !field.optional {
141 gen_optionalized_field_to_core(&field.name, &field.ty, config, false)
144 } else {
145 field_conversion_to_core_cfg(&field.name, &field.ty, field.optional, config)
146 };
147 let conversion = if let Some(newtype_path) = &field.newtype_wrapper {
153 if let Some(expr) = conversion.strip_prefix(&format!("{}: ", field.name)) {
154 match &field.ty {
157 TypeRef::Optional(_) => format!("{}: ({expr}).map({newtype_path})", field.name),
158 TypeRef::Vec(_) => {
159 format!("{}: ({expr}).into_iter().map({newtype_path}).collect()", field.name)
160 }
161 _ if field.optional => format!("{}: ({expr}).map({newtype_path})", field.name),
162 _ => format!("{}: {newtype_path}({expr})", field.name),
163 }
164 } else {
165 conversion
166 }
167 } else {
168 conversion
169 };
170 let conversion = if field.is_boxed && matches!(&field.ty, TypeRef::Named(_)) {
172 if let Some(expr) = conversion.strip_prefix(&format!("{}: ", field.name)) {
173 if field.optional {
174 format!("{}: {}.map(Box::new)", field.name, expr)
176 } else {
177 format!("{}: Box::new({})", field.name, expr)
178 }
179 } else {
180 conversion
181 }
182 } else {
183 conversion
184 };
185 let is_opaque_arc_field = field.core_wrapper == CoreWrapper::Arc
193 && matches!(&field.ty, TypeRef::Named(n) if config
194 .opaque_types
195 .is_some_and(|opaque| opaque.contains(n.as_str())));
196 let conversion = if is_opaque_arc_field {
197 if field.optional {
198 format!("{}: val.{}.map(|v| v.inner)", field.name, field.name)
199 } else {
200 format!("{}: val.{}.inner", field.name, field.name)
201 }
202 } else {
203 apply_core_wrapper_to_core(
204 &conversion,
205 &field.name,
206 &field.core_wrapper,
207 &field.vec_inner_core_wrapper,
208 field.optional,
209 )
210 };
211 let binding_name = config.binding_field_name_owned(&typ.name, &field.name);
215 let conversion = if binding_name != field.name {
216 conversion.replace(&format!("val.{}", field.name), &format!("val.{binding_name}"))
217 } else {
218 conversion
219 };
220 writeln!(out, " {conversion},").ok();
221 }
222 if typ.has_stripped_cfg_fields {
224 writeln!(out, " ..Default::default()").ok();
225 }
226 writeln!(out, " }}").ok();
227 writeln!(out, " }}").ok();
228 write!(out, "}}").ok();
229 out
230}
231
232pub(super) fn gen_optionalized_field_to_core(
237 name: &str,
238 ty: &TypeRef,
239 config: &ConversionConfig,
240 field_is_ir_optional: bool,
241) -> String {
242 match ty {
243 TypeRef::Json => {
244 format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok()).unwrap_or_default()")
245 }
246 TypeRef::Named(_) => {
247 format!("{name}: val.{name}.map(Into::into).unwrap_or_default()")
249 }
250 TypeRef::Primitive(PrimitiveType::F32) if config.cast_f32_to_f64 => {
251 format!("{name}: val.{name}.map(|v| v as f32).unwrap_or(0.0)")
252 }
253 TypeRef::Primitive(PrimitiveType::F32 | PrimitiveType::F64) => {
254 format!("{name}: val.{name}.unwrap_or(0.0)")
255 }
256 TypeRef::Primitive(p) if config.cast_large_ints_to_i64 && needs_i64_cast(p) => {
257 let core_ty = core_prim_str(p);
258 format!("{name}: val.{name}.map(|v| v as {core_ty}).unwrap_or_default()")
259 }
260 TypeRef::Optional(inner)
261 if config.cast_large_ints_to_i64
262 && matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
263 {
264 if let TypeRef::Primitive(p) = inner.as_ref() {
265 let core_ty = core_prim_str(p);
266 format!("{name}: val.{name}.map(|v| v as {core_ty})")
267 } else {
268 field_conversion_to_core(name, ty, false)
269 }
270 }
271 TypeRef::Duration if config.cast_large_ints_to_i64 => {
272 format!("{name}: val.{name}.map(|v| std::time::Duration::from_millis(v as u64)).unwrap_or_default()")
273 }
274 TypeRef::Duration => {
275 format!("{name}: val.{name}.map(std::time::Duration::from_millis).unwrap_or_default()")
276 }
277 TypeRef::Path => {
278 format!("{name}: val.{name}.map(Into::into).unwrap_or_default()")
279 }
280 TypeRef::Optional(inner) if matches!(inner.as_ref(), TypeRef::Path) => {
281 format!("{name}: val.{name}.map(|s| std::path::PathBuf::from(s))")
283 }
284 TypeRef::Optional(_) => {
285 format!("{name}: val.{name}.map(Some)")
288 }
289 TypeRef::Char => {
291 format!("{name}: val.{name}.and_then(|s| s.chars().next()).unwrap_or('*')")
292 }
293 TypeRef::Vec(inner) => match inner.as_ref() {
294 TypeRef::Json => {
295 format!(
296 "{name}: val.{name}.map(|v| v.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect()).unwrap_or_default()"
297 )
298 }
299 TypeRef::Named(_) => {
300 format!("{name}: val.{name}.map(|v| v.into_iter().map(Into::into).collect()).unwrap_or_default()")
301 }
302 TypeRef::Primitive(p) if config.cast_large_ints_to_i64 && needs_i64_cast(p) => {
303 let core_ty = core_prim_str(p);
304 format!(
305 "{name}: val.{name}.map(|v| v.into_iter().map(|x| x as {core_ty}).collect()).unwrap_or_default()"
306 )
307 }
308 _ => format!("{name}: val.{name}.unwrap_or_default()"),
309 },
310 TypeRef::Map(k, v) if matches!(v.as_ref(), TypeRef::Json) => {
311 let k_is_json = matches!(k.as_ref(), TypeRef::Json);
315 let k_expr = if k_is_json {
316 "serde_json::from_str(&k).unwrap_or_default()"
317 } else {
318 "k.into()"
319 };
320 format!(
321 "{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()"
322 )
323 }
324 TypeRef::Map(k, _v) if matches!(k.as_ref(), TypeRef::Json) => {
325 format!(
327 "{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (serde_json::from_str(&k).unwrap_or_default(), v)).collect()"
328 )
329 }
330 TypeRef::Map(k, v) => {
331 let has_named_val = matches!(v.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n));
333 let has_named_key = matches!(k.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n));
334 let val_is_string_enum = matches!(v.as_ref(), TypeRef::Named(n)
335 if config.enum_string_names.as_ref().is_some_and(|names| names.contains(n)));
336 if field_is_ir_optional {
337 if val_is_string_enum {
339 format!(
340 "{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| (k, serde_json::from_str(&v).unwrap_or_default())).collect())"
341 )
342 } else if has_named_val {
343 format!("{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| (k, v.into())).collect())")
344 } else if has_named_key {
345 format!("{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| (k.into(), v)).collect())")
346 } else {
347 format!("{name}: val.{name}.map(|m| m.into_iter().collect())")
348 }
349 } else if val_is_string_enum {
350 format!(
351 "{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (k, serde_json::from_str(&v).unwrap_or_default())).collect()"
352 )
353 } else if has_named_val {
354 format!("{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (k, v.into())).collect()")
355 } else if has_named_key {
356 format!("{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (k.into(), v)).collect()")
357 } else {
358 format!("{name}: val.{name}.unwrap_or_default().into_iter().collect()")
359 }
360 }
361 _ => {
362 format!("{name}: val.{name}.unwrap_or_default()")
364 }
365 }
366}
367
368pub fn field_conversion_to_core(name: &str, ty: &TypeRef, optional: bool) -> String {
370 match ty {
371 TypeRef::Primitive(_) | TypeRef::String | TypeRef::Unit => {
373 format!("{name}: val.{name}")
374 }
375 TypeRef::Bytes => {
377 if optional {
378 format!("{name}: val.{name}.map(Into::into)")
379 } else {
380 format!("{name}: val.{name}.into()")
381 }
382 }
383 TypeRef::Json => {
385 if optional {
386 format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok())")
387 } else {
388 format!("{name}: serde_json::from_str(&val.{name}).unwrap_or_default()")
389 }
390 }
391 TypeRef::Char => {
393 if optional {
394 format!("{name}: val.{name}.and_then(|s| s.chars().next())")
395 } else {
396 format!("{name}: val.{name}.chars().next().unwrap_or('*')")
397 }
398 }
399 TypeRef::Duration => {
401 if optional {
402 format!("{name}: val.{name}.map(std::time::Duration::from_millis)")
403 } else {
404 format!("{name}: std::time::Duration::from_millis(val.{name})")
405 }
406 }
407 TypeRef::Path => {
409 if optional {
410 format!("{name}: val.{name}.map(Into::into)")
411 } else {
412 format!("{name}: val.{name}.into()")
413 }
414 }
415 TypeRef::Named(type_name) if is_tuple_type_name(type_name) => {
418 format!("{name}: val.{name}")
419 }
420 TypeRef::Named(_) => {
421 if optional {
422 format!("{name}: val.{name}.map(Into::into)")
423 } else {
424 format!("{name}: val.{name}.into()")
425 }
426 }
427 TypeRef::Map(k, v) if matches!(v.as_ref(), TypeRef::Json) => {
431 let k_expr = if matches!(k.as_ref(), TypeRef::Json) {
432 "serde_json::from_str(&k).unwrap_or_default()"
433 } else {
434 "k.into()"
435 };
436 if optional {
437 format!(
438 "{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| ({k_expr}, serde_json::from_str(&v).unwrap_or_default())).collect())"
439 )
440 } else {
441 format!(
442 "{name}: val.{name}.into_iter().map(|(k, v)| ({k_expr}, serde_json::from_str(&v).unwrap_or_default())).collect()"
443 )
444 }
445 }
446 TypeRef::Optional(inner) => match inner.as_ref() {
448 TypeRef::Json => format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok())"),
449 TypeRef::Named(_) | TypeRef::Path => format!("{name}: val.{name}.map(Into::into)"),
450 TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Named(_)) => {
451 format!("{name}: val.{name}.map(|v| v.into_iter().map(Into::into).collect())")
452 }
453 _ => format!("{name}: val.{name}"),
454 },
455 TypeRef::Vec(inner) => match inner.as_ref() {
457 TypeRef::Json => {
458 if optional {
459 format!(
460 "{name}: val.{name}.map(|v| v.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect())"
461 )
462 } else {
463 format!("{name}: val.{name}.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect()")
464 }
465 }
466 TypeRef::Named(type_name) if is_tuple_type_name(type_name) => {
468 format!("{name}: val.{name}")
469 }
470 TypeRef::Named(_) => {
471 if optional {
472 format!("{name}: val.{name}.map(|v| v.into_iter().map(Into::into).collect())")
473 } else {
474 format!("{name}: val.{name}.into_iter().map(Into::into).collect()")
475 }
476 }
477 _ => format!("{name}: val.{name}"),
478 },
479 TypeRef::Map(k, v) => {
482 let has_named_key = matches!(k.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n));
483 let has_named_val = matches!(v.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n));
484 let has_json_val = matches!(v.as_ref(), TypeRef::Json);
485 let has_json_key = matches!(k.as_ref(), TypeRef::Json);
486 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)));
488 let has_vec_json_val = matches!(v.as_ref(), TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Json));
490 if has_json_val || has_json_key || has_named_key || has_named_val || has_vec_named_val || has_vec_json_val {
491 let k_expr = if has_json_key {
495 "serde_json::from_str(&k).unwrap_or(serde_json::Value::String(k))"
496 } else {
497 "k.into()"
498 };
499 let v_expr = if has_json_val {
500 "serde_json::from_str(&v).unwrap_or(serde_json::Value::String(v))"
501 } else if has_named_val {
502 "v.into()"
503 } else if has_vec_named_val {
504 "v.into_iter().map(Into::into).collect()"
505 } else if has_vec_json_val {
506 "v.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect()"
507 } else {
508 "v"
509 };
510 if optional {
511 format!("{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| ({k_expr}, {v_expr})).collect())")
512 } else {
513 format!("{name}: val.{name}.into_iter().map(|(k, v)| ({k_expr}, {v_expr})).collect()")
514 }
515 } else {
516 if optional {
520 if has_named_val {
521 format!("{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| (k, v.into())).collect())")
522 } else {
523 format!("{name}: val.{name}.map(|m| m.into_iter().collect())")
524 }
525 } else {
526 format!("{name}: val.{name}.into_iter().collect()")
527 }
528 }
529 }
530 }
531}
532
533pub fn field_conversion_to_core_cfg(name: &str, ty: &TypeRef, optional: bool, config: &ConversionConfig) -> String {
535 if optional && matches!(ty, TypeRef::Optional(_)) {
539 let inner_expr = field_conversion_to_core_cfg(name, ty, false, config);
542 if let Some(expr) = inner_expr.strip_prefix(&format!("{name}: ")) {
544 return format!("{name}: ({expr}).map(Some)");
545 }
546 return inner_expr;
547 }
548
549 if config.map_uses_jsvalue {
551 let is_nested_vec = matches!(ty, TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Vec(_)));
552 let is_vec_json = matches!(ty, TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Json));
553 let is_map = matches!(ty, TypeRef::Map(_, _));
554 if is_nested_vec || is_map || is_vec_json {
555 if optional {
556 return format!(
557 "{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::from_value(v.clone()).ok())"
558 );
559 }
560 return format!("{name}: serde_wasm_bindgen::from_value(val.{name}.clone()).unwrap_or_default()");
561 }
562 if let TypeRef::Optional(inner) = ty {
563 let is_inner_nested = matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Vec(_)));
564 let is_inner_vec_json = matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Json));
565 let is_inner_map = matches!(inner.as_ref(), TypeRef::Map(_, _));
566 if is_inner_nested || is_inner_map || is_inner_vec_json {
567 return format!(
568 "{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::from_value(v.clone()).ok())"
569 );
570 }
571 }
572 }
573
574 if config.vec_named_to_string {
578 if let TypeRef::Vec(inner) = ty {
579 if matches!(inner.as_ref(), TypeRef::Named(_)) {
580 if optional {
581 return format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok())");
582 }
583 return format!("{name}: serde_json::from_str(&val.{name}).unwrap_or_default()");
584 }
585 }
586 }
587 if config.map_as_string && matches!(ty, TypeRef::Map(_, _)) {
589 return format!("{name}: Default::default()");
590 }
591 if config.map_as_string {
592 if let TypeRef::Optional(inner) = ty {
593 if matches!(inner.as_ref(), TypeRef::Map(_, _)) {
594 return format!("{name}: Default::default()");
595 }
596 }
597 }
598 if config.json_to_string && matches!(ty, TypeRef::Json) {
600 return format!("{name}: Default::default()");
601 }
602 if config.map_uses_jsvalue && matches!(ty, TypeRef::Json) {
604 if optional {
605 return format!("{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::from_value(v.clone()).ok())");
606 }
607 return format!("{name}: serde_wasm_bindgen::from_value(val.{name}.clone()).unwrap_or_default()");
608 }
609 if !config.cast_large_ints_to_i64
610 && !config.cast_f32_to_f64
611 && !config.json_to_string
612 && !config.vec_named_to_string
613 && !config.map_as_string
614 {
615 return field_conversion_to_core(name, ty, optional);
616 }
617 match ty {
619 TypeRef::Primitive(p) if config.cast_large_ints_to_i64 && needs_i64_cast(p) => {
620 let core_ty = core_prim_str(p);
621 if optional {
622 format!("{name}: val.{name}.map(|v| v as {core_ty})")
623 } else {
624 format!("{name}: val.{name} as {core_ty}")
625 }
626 }
627 TypeRef::Primitive(PrimitiveType::F32) if config.cast_f32_to_f64 => {
629 if optional {
630 format!("{name}: val.{name}.map(|v| v as f32)")
631 } else {
632 format!("{name}: val.{name} as f32")
633 }
634 }
635 TypeRef::Duration if config.cast_large_ints_to_i64 => {
636 if optional {
637 format!("{name}: val.{name}.map(|v| std::time::Duration::from_millis(v as u64))")
638 } else {
639 format!("{name}: std::time::Duration::from_millis(val.{name} as u64)")
640 }
641 }
642 TypeRef::Optional(inner) if matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) => {
643 if let TypeRef::Primitive(p) = inner.as_ref() {
644 let core_ty = core_prim_str(p);
645 format!("{name}: val.{name}.map(|v| v as {core_ty})")
646 } else {
647 field_conversion_to_core(name, ty, optional)
648 }
649 }
650 TypeRef::Vec(inner)
652 if config.cast_large_ints_to_i64
653 && matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
654 {
655 if let TypeRef::Primitive(p) = inner.as_ref() {
656 let core_ty = core_prim_str(p);
657 if optional {
658 format!("{name}: val.{name}.map(|v| v.into_iter().map(|x| x as {core_ty}).collect())")
659 } else {
660 format!("{name}: val.{name}.into_iter().map(|v| v as {core_ty}).collect()")
661 }
662 } else {
663 field_conversion_to_core(name, ty, optional)
664 }
665 }
666 TypeRef::Map(_k, v)
668 if config.cast_large_ints_to_i64 && matches!(v.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
669 {
670 if let TypeRef::Primitive(p) = v.as_ref() {
671 let core_ty = core_prim_str(p);
672 if optional {
673 format!("{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| (k, v as {core_ty})).collect())")
674 } else {
675 format!("{name}: val.{name}.into_iter().map(|(k, v)| (k, v as {core_ty})).collect()")
676 }
677 } else {
678 field_conversion_to_core(name, ty, optional)
679 }
680 }
681 TypeRef::Vec(inner)
683 if config.cast_f32_to_f64 && matches!(inner.as_ref(), TypeRef::Primitive(PrimitiveType::F32)) =>
684 {
685 if optional {
686 format!("{name}: val.{name}.map(|v| v.into_iter().map(|x| x as f32).collect())")
687 } else {
688 format!("{name}: val.{name}.into_iter().map(|v| v as f32).collect()")
689 }
690 }
691 TypeRef::Optional(inner)
693 if config.cast_f32_to_f64
694 && matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Primitive(PrimitiveType::F32))) =>
695 {
696 format!("{name}: val.{name}.map(|v| v.into_iter().map(|x| x as f32).collect())")
697 }
698 _ => field_conversion_to_core(name, ty, optional),
700 }
701}
702
703fn apply_core_wrapper_to_core(
706 conversion: &str,
707 name: &str,
708 core_wrapper: &CoreWrapper,
709 vec_inner_core_wrapper: &CoreWrapper,
710 optional: bool,
711) -> String {
712 if *vec_inner_core_wrapper == CoreWrapper::Arc {
714 return conversion
715 .replace(
716 ".map(Into::into).collect()",
717 ".map(|v| std::sync::Arc::new(v.into())).collect()",
718 )
719 .replace(
720 "map(|v| v.into_iter().map(Into::into)",
721 "map(|v| v.into_iter().map(|v| std::sync::Arc::new(v.into()))",
722 );
723 }
724
725 match core_wrapper {
726 CoreWrapper::None => conversion.to_string(),
727 CoreWrapper::Cow => {
728 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
732 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::Arc => {
748 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
750 if expr == "Default::default()" {
751 conversion.to_string()
754 } else if optional {
755 format!("{name}: {expr}.map(|v| std::sync::Arc::new(v))")
756 } else {
757 format!("{name}: std::sync::Arc::new({expr})")
758 }
759 } else {
760 conversion.to_string()
761 }
762 }
763 CoreWrapper::Bytes => {
764 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
770 let already_converted_non_opt = expr == format!("val.{name}.into()");
771 let already_converted_opt = expr
772 .strip_prefix(&format!("val.{name}"))
773 .map(|s| s == ".map(Into::into)")
774 .unwrap_or(false);
775 if already_converted_non_opt || already_converted_opt {
776 conversion.to_string()
778 } else if optional {
779 format!("{name}: {expr}.map(Into::into)")
780 } else if expr == format!("val.{name}") {
781 format!("{name}: val.{name}.into()")
782 } else if expr == "Default::default()" {
783 conversion.to_string()
786 } else {
787 format!("{name}: ({expr}).into()")
788 }
789 } else {
790 conversion.to_string()
791 }
792 }
793 CoreWrapper::ArcMutex => {
794 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
796 if optional {
797 format!("{name}: {expr}.map(|v| std::sync::Arc::new(std::sync::Mutex::new(v.into())))")
798 } else if expr == format!("val.{name}") {
799 format!("{name}: std::sync::Arc::new(std::sync::Mutex::new(val.{name}.into()))")
800 } else {
801 format!("{name}: std::sync::Arc::new(std::sync::Mutex::new(({expr}).into()))")
802 }
803 } else {
804 conversion.to_string()
805 }
806 }
807 }
808}