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 if !references_excluded && is_sanitized_vec_primitive(&field.ty) {
134 gen_sanitized_vec_primitive_to_core(&field.name, &field.ty, field.optional)
135 } else {
136 format!("{}: Default::default()", field.name)
137 }
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 conversion = apply_core_wrapper_to_core(
185 &conversion,
186 &field.name,
187 &field.core_wrapper,
188 &field.vec_inner_core_wrapper,
189 field.optional,
190 );
191 writeln!(out, " {conversion},").ok();
192 }
193 if typ.has_stripped_cfg_fields {
195 writeln!(out, " ..Default::default()").ok();
196 }
197 writeln!(out, " }}").ok();
198 writeln!(out, " }}").ok();
199 write!(out, "}}").ok();
200 out
201}
202
203pub(super) fn gen_optionalized_field_to_core(name: &str, ty: &TypeRef, config: &ConversionConfig) -> String {
206 match ty {
207 TypeRef::Json => {
208 format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok()).unwrap_or_default()")
209 }
210 TypeRef::Named(_) => {
211 format!("{name}: val.{name}.map(Into::into).unwrap_or_default()")
213 }
214 TypeRef::Primitive(PrimitiveType::F32) if config.cast_f32_to_f64 => {
215 format!("{name}: val.{name}.map(|v| v as f32).unwrap_or(0.0)")
216 }
217 TypeRef::Primitive(PrimitiveType::F32 | PrimitiveType::F64) => {
218 format!("{name}: val.{name}.unwrap_or(0.0)")
219 }
220 TypeRef::Primitive(p) if config.cast_large_ints_to_i64 && needs_i64_cast(p) => {
221 let core_ty = core_prim_str(p);
222 format!("{name}: val.{name}.map(|v| v as {core_ty}).unwrap_or_default()")
223 }
224 TypeRef::Optional(inner)
225 if config.cast_large_ints_to_i64
226 && matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
227 {
228 if let TypeRef::Primitive(p) = inner.as_ref() {
229 let core_ty = core_prim_str(p);
230 format!("{name}: val.{name}.map(|v| v as {core_ty})")
231 } else {
232 field_conversion_to_core(name, ty, false)
233 }
234 }
235 TypeRef::Duration if config.cast_large_ints_to_i64 => {
236 format!("{name}: val.{name}.map(|v| std::time::Duration::from_millis(v as u64)).unwrap_or_default()")
237 }
238 TypeRef::Duration => {
239 format!("{name}: val.{name}.map(std::time::Duration::from_millis).unwrap_or_default()")
240 }
241 TypeRef::Path => {
242 format!("{name}: val.{name}.map(Into::into).unwrap_or_default()")
243 }
244 TypeRef::Optional(inner) if matches!(inner.as_ref(), TypeRef::Path) => {
245 format!("{name}: val.{name}.map(|s| std::path::PathBuf::from(s))")
247 }
248 TypeRef::Optional(_) => {
249 format!("{name}: val.{name}.map(Some)")
252 }
253 TypeRef::Char => {
255 format!("{name}: val.{name}.and_then(|s| s.chars().next()).unwrap_or('*')")
256 }
257 TypeRef::Vec(inner) => match inner.as_ref() {
258 TypeRef::Json => {
259 format!(
260 "{name}: val.{name}.map(|v| v.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect()).unwrap_or_default()"
261 )
262 }
263 TypeRef::Named(_) => {
264 format!("{name}: val.{name}.map(|v| v.into_iter().map(Into::into).collect()).unwrap_or_default()")
265 }
266 TypeRef::Primitive(p) if config.cast_large_ints_to_i64 && needs_i64_cast(p) => {
267 let core_ty = core_prim_str(p);
268 format!(
269 "{name}: val.{name}.map(|v| v.into_iter().map(|x| x as {core_ty}).collect()).unwrap_or_default()"
270 )
271 }
272 _ => format!("{name}: val.{name}.unwrap_or_default()"),
273 },
274 TypeRef::Map(k, v) if matches!(v.as_ref(), TypeRef::Json) => {
275 let k_is_json = matches!(k.as_ref(), TypeRef::Json);
277 let k_expr = if k_is_json {
278 "serde_json::from_str(&k).unwrap_or_default()"
279 } else {
280 "k"
281 };
282 format!(
283 "{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()"
284 )
285 }
286 TypeRef::Map(k, _v) if matches!(k.as_ref(), TypeRef::Json) => {
287 format!(
289 "{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (serde_json::from_str(&k).unwrap_or_default(), v)).collect()"
290 )
291 }
292 TypeRef::Map(k, v) => {
293 let has_named_val = matches!(v.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n));
295 if has_named_val {
296 format!("{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (k, v.into())).collect()")
297 } else if matches!(k.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n)) {
298 format!("{name}: val.{name}.unwrap_or_default().into_iter().map(|(k, v)| (k.into(), v)).collect()")
299 } else {
300 format!("{name}: val.{name}.unwrap_or_default().into_iter().collect()")
301 }
302 }
303 _ => {
304 format!("{name}: val.{name}.unwrap_or_default()")
306 }
307 }
308}
309
310pub fn field_conversion_to_core(name: &str, ty: &TypeRef, optional: bool) -> String {
312 match ty {
313 TypeRef::Primitive(_) | TypeRef::String | TypeRef::Bytes | TypeRef::Unit => {
315 format!("{name}: val.{name}")
316 }
317 TypeRef::Json => {
319 if optional {
320 format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok())")
321 } else {
322 format!("{name}: serde_json::from_str(&val.{name}).unwrap_or_default()")
323 }
324 }
325 TypeRef::Char => {
327 if optional {
328 format!("{name}: val.{name}.and_then(|s| s.chars().next())")
329 } else {
330 format!("{name}: val.{name}.chars().next().unwrap_or('*')")
331 }
332 }
333 TypeRef::Duration => {
335 if optional {
336 format!("{name}: val.{name}.map(std::time::Duration::from_millis)")
337 } else {
338 format!("{name}: std::time::Duration::from_millis(val.{name})")
339 }
340 }
341 TypeRef::Path => {
343 if optional {
344 format!("{name}: val.{name}.map(Into::into)")
345 } else {
346 format!("{name}: val.{name}.into()")
347 }
348 }
349 TypeRef::Named(type_name) if is_tuple_type_name(type_name) => {
352 format!("{name}: val.{name}")
353 }
354 TypeRef::Named(_) => {
355 if optional {
356 format!("{name}: val.{name}.map(Into::into)")
357 } else {
358 format!("{name}: val.{name}.into()")
359 }
360 }
361 TypeRef::Map(k, v) if matches!(v.as_ref(), TypeRef::Json) => {
363 let k_expr = if matches!(k.as_ref(), TypeRef::Json) {
364 "serde_json::from_str(&k).unwrap_or_default()"
365 } else {
366 "k"
367 };
368 if optional {
369 format!(
370 "{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| ({k_expr}, serde_json::from_str(&v).unwrap_or_default())).collect())"
371 )
372 } else {
373 format!(
374 "{name}: val.{name}.into_iter().map(|(k, v)| ({k_expr}, serde_json::from_str(&v).unwrap_or_default())).collect()"
375 )
376 }
377 }
378 TypeRef::Optional(inner) => match inner.as_ref() {
380 TypeRef::Json => format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok())"),
381 TypeRef::Named(_) | TypeRef::Path => format!("{name}: val.{name}.map(Into::into)"),
382 TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Named(_)) => {
383 format!("{name}: val.{name}.map(|v| v.into_iter().map(Into::into).collect())")
384 }
385 _ => format!("{name}: val.{name}"),
386 },
387 TypeRef::Vec(inner) => match inner.as_ref() {
389 TypeRef::Json => {
390 if optional {
391 format!(
392 "{name}: val.{name}.map(|v| v.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect())"
393 )
394 } else {
395 format!("{name}: val.{name}.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect()")
396 }
397 }
398 TypeRef::Named(type_name) if is_tuple_type_name(type_name) => {
400 format!("{name}: val.{name}")
401 }
402 TypeRef::Named(_) => {
403 if optional {
404 format!("{name}: val.{name}.map(|v| v.into_iter().map(Into::into).collect())")
405 } else {
406 format!("{name}: val.{name}.into_iter().map(Into::into).collect()")
407 }
408 }
409 _ => format!("{name}: val.{name}"),
410 },
411 TypeRef::Map(k, v) => {
414 let has_named_key = matches!(k.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n));
415 let has_named_val = matches!(v.as_ref(), TypeRef::Named(n) if !is_tuple_type_name(n));
416 let has_json_val = matches!(v.as_ref(), TypeRef::Json);
417 let has_json_key = matches!(k.as_ref(), TypeRef::Json);
418 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)));
420 let has_vec_json_val = matches!(v.as_ref(), TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Json));
422 if has_json_val || has_json_key || has_named_key || has_named_val || has_vec_named_val || has_vec_json_val {
423 let k_expr = if has_json_key {
424 "serde_json::from_str(&k).unwrap_or(serde_json::Value::String(k))"
425 } else if has_named_key {
426 "k.into()"
427 } else {
428 "k"
429 };
430 let v_expr = if has_json_val {
431 "serde_json::from_str(&v).unwrap_or(serde_json::Value::String(v))"
432 } else if has_named_val {
433 "v.into()"
434 } else if has_vec_named_val {
435 "v.into_iter().map(Into::into).collect()"
436 } else if has_vec_json_val {
437 "v.into_iter().filter_map(|s| serde_json::from_str(&s).ok()).collect()"
438 } else {
439 "v"
440 };
441 if optional {
442 format!("{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| ({k_expr}, {v_expr})).collect())")
443 } else {
444 format!("{name}: val.{name}.into_iter().map(|(k, v)| ({k_expr}, {v_expr})).collect()")
445 }
446 } else {
447 if optional {
449 format!("{name}: val.{name}.map(|m| m.into_iter().collect())")
450 } else {
451 format!("{name}: val.{name}.into_iter().collect()")
452 }
453 }
454 }
455 }
456}
457
458pub fn field_conversion_to_core_cfg(name: &str, ty: &TypeRef, optional: bool, config: &ConversionConfig) -> String {
460 if optional && matches!(ty, TypeRef::Optional(_)) {
464 let inner_expr = field_conversion_to_core_cfg(name, ty, false, config);
467 if let Some(expr) = inner_expr.strip_prefix(&format!("{name}: ")) {
469 return format!("{name}: ({expr}).map(Some)");
470 }
471 return inner_expr;
472 }
473
474 if config.map_uses_jsvalue {
476 let is_nested_vec = matches!(ty, TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Vec(_)));
477 let is_vec_json = matches!(ty, TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Json));
478 let is_map = matches!(ty, TypeRef::Map(_, _));
479 if is_nested_vec || is_map || is_vec_json {
480 if optional {
481 return format!(
482 "{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::from_value(v.clone()).ok())"
483 );
484 }
485 return format!("{name}: serde_wasm_bindgen::from_value(val.{name}.clone()).unwrap_or_default()");
486 }
487 if let TypeRef::Optional(inner) = ty {
488 let is_inner_nested = matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Vec(_)));
489 let is_inner_vec_json = matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Json));
490 let is_inner_map = matches!(inner.as_ref(), TypeRef::Map(_, _));
491 if is_inner_nested || is_inner_map || is_inner_vec_json {
492 return format!(
493 "{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::from_value(v.clone()).ok())"
494 );
495 }
496 }
497 }
498
499 if config.vec_named_to_string {
503 if let TypeRef::Vec(_) = ty {
504 if optional {
505 return format!("{name}: val.{name}.as_ref().and_then(|s| serde_json::from_str(s).ok())");
506 }
507 return format!("{name}: serde_json::from_str(&val.{name}).unwrap_or_default()");
508 }
509 }
510 if config.json_to_string && matches!(ty, TypeRef::Json) {
512 return format!("{name}: Default::default()");
513 }
514 if config.map_uses_jsvalue && matches!(ty, TypeRef::Json) {
516 if optional {
517 return format!("{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::from_value(v.clone()).ok())");
518 }
519 return format!("{name}: serde_wasm_bindgen::from_value(val.{name}.clone()).unwrap_or_default()");
520 }
521 if !config.cast_large_ints_to_i64
522 && !config.cast_f32_to_f64
523 && !config.json_to_string
524 && !config.vec_named_to_string
525 {
526 return field_conversion_to_core(name, ty, optional);
527 }
528 match ty {
530 TypeRef::Primitive(p) if config.cast_large_ints_to_i64 && needs_i64_cast(p) => {
531 let core_ty = core_prim_str(p);
532 if optional {
533 format!("{name}: val.{name}.map(|v| v as {core_ty})")
534 } else {
535 format!("{name}: val.{name} as {core_ty}")
536 }
537 }
538 TypeRef::Primitive(PrimitiveType::F32) if config.cast_f32_to_f64 => {
540 if optional {
541 format!("{name}: val.{name}.map(|v| v as f32)")
542 } else {
543 format!("{name}: val.{name} as f32")
544 }
545 }
546 TypeRef::Duration if config.cast_large_ints_to_i64 => {
547 if optional {
548 format!("{name}: val.{name}.map(|v| std::time::Duration::from_millis(v as u64))")
549 } else {
550 format!("{name}: std::time::Duration::from_millis(val.{name} as u64)")
551 }
552 }
553 TypeRef::Optional(inner) if matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) => {
554 if let TypeRef::Primitive(p) = inner.as_ref() {
555 let core_ty = core_prim_str(p);
556 format!("{name}: val.{name}.map(|v| v as {core_ty})")
557 } else {
558 field_conversion_to_core(name, ty, optional)
559 }
560 }
561 TypeRef::Vec(inner)
563 if config.cast_large_ints_to_i64
564 && matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
565 {
566 if let TypeRef::Primitive(p) = inner.as_ref() {
567 let core_ty = core_prim_str(p);
568 if optional {
569 format!("{name}: val.{name}.map(|v| v.into_iter().map(|x| x as {core_ty}).collect())")
570 } else {
571 format!("{name}: val.{name}.into_iter().map(|v| v as {core_ty}).collect()")
572 }
573 } else {
574 field_conversion_to_core(name, ty, optional)
575 }
576 }
577 TypeRef::Map(_k, v)
579 if config.cast_large_ints_to_i64 && matches!(v.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
580 {
581 if let TypeRef::Primitive(p) = v.as_ref() {
582 let core_ty = core_prim_str(p);
583 if optional {
584 format!("{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| (k, v as {core_ty})).collect())")
585 } else {
586 format!("{name}: val.{name}.into_iter().map(|(k, v)| (k, v as {core_ty})).collect()")
587 }
588 } else {
589 field_conversion_to_core(name, ty, optional)
590 }
591 }
592 TypeRef::Vec(inner)
594 if config.cast_f32_to_f64 && matches!(inner.as_ref(), TypeRef::Primitive(PrimitiveType::F32)) =>
595 {
596 if optional {
597 format!("{name}: val.{name}.map(|v| v.into_iter().map(|x| x as f32).collect())")
598 } else {
599 format!("{name}: val.{name}.into_iter().map(|v| v as f32).collect()")
600 }
601 }
602 TypeRef::Optional(inner)
604 if config.cast_f32_to_f64
605 && matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Primitive(PrimitiveType::F32))) =>
606 {
607 format!("{name}: val.{name}.map(|v| v.into_iter().map(|x| x as f32).collect())")
608 }
609 _ => field_conversion_to_core(name, ty, optional),
611 }
612}
613
614fn apply_core_wrapper_to_core(
617 conversion: &str,
618 name: &str,
619 core_wrapper: &CoreWrapper,
620 vec_inner_core_wrapper: &CoreWrapper,
621 optional: bool,
622) -> String {
623 if *vec_inner_core_wrapper == CoreWrapper::Arc {
625 return conversion
626 .replace(
627 ".map(Into::into).collect()",
628 ".map(|v| std::sync::Arc::new(v.into())).collect()",
629 )
630 .replace(
631 "map(|v| v.into_iter().map(Into::into)",
632 "map(|v| v.into_iter().map(|v| std::sync::Arc::new(v.into()))",
633 );
634 }
635
636 match core_wrapper {
637 CoreWrapper::None => conversion.to_string(),
638 CoreWrapper::Cow => {
639 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
643 if optional {
644 format!("{name}: {expr}.map(Into::into)")
645 } else if expr == format!("val.{name}") {
646 format!("{name}: val.{name}.into()")
647 } else if expr == "Default::default()" {
648 conversion.to_string()
651 } else {
652 format!("{name}: ({expr}).into()")
653 }
654 } else {
655 conversion.to_string()
656 }
657 }
658 CoreWrapper::Arc => {
659 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
661 if expr == "Default::default()" {
662 conversion.to_string()
665 } else if optional {
666 format!("{name}: {expr}.map(|v| std::sync::Arc::new(v))")
667 } else {
668 format!("{name}: std::sync::Arc::new({expr})")
669 }
670 } else {
671 conversion.to_string()
672 }
673 }
674 CoreWrapper::Bytes => {
675 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
677 if optional {
678 format!("{name}: {expr}.map(Into::into)")
679 } else if expr == format!("val.{name}") {
680 format!("{name}: val.{name}.into()")
681 } else if expr == "Default::default()" {
682 conversion.to_string()
685 } else {
686 format!("{name}: ({expr}).into()")
687 }
688 } else {
689 conversion.to_string()
690 }
691 }
692 CoreWrapper::ArcMutex => {
693 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
695 if optional {
696 format!("{name}: {expr}.map(|v| std::sync::Arc::new(std::sync::Mutex::new(v.into())))")
697 } else if expr == format!("val.{name}") {
698 format!("{name}: std::sync::Arc::new(std::sync::Mutex::new(val.{name}.into()))")
699 } else {
700 format!("{name}: std::sync::Arc::new(std::sync::Mutex::new(({expr}).into()))")
701 }
702 } else {
703 conversion.to_string()
704 }
705 }
706 }
707}
708
709fn is_sanitized_vec_primitive(ty: &TypeRef) -> bool {
713 match ty {
714 TypeRef::Vec(inner) => matches!(inner.as_ref(), TypeRef::Primitive(_)),
715 TypeRef::Optional(inner) => {
716 matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Primitive(_)))
717 }
718 _ => false,
719 }
720}
721
722fn gen_sanitized_vec_primitive_to_core(name: &str, ty: &TypeRef, optional: bool) -> String {
725 let is_option_vec = matches!(ty, TypeRef::Optional(inner) if matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Primitive(_))));
727 if is_option_vec || optional {
728 return format!(
729 "{name}: val.{name}.as_ref().and_then(|v| serde_json::to_value(v).ok()).and_then(|v| serde_json::from_value(v).ok())"
730 );
731 }
732 format!(
734 "{name}: serde_json::to_value(&val.{name}).ok().and_then(|v| serde_json::from_value(v).ok()).unwrap_or_default()"
735 )
736}