1use ahash::AHashSet;
2use alef_core::ir::{CoreWrapper, PrimitiveType, TypeDef, TypeRef};
3use std::fmt::Write;
4
5use super::ConversionConfig;
6use super::binding_to_core::field_conversion_to_core;
7use super::helpers::is_newtype;
8use super::helpers::{binding_prim_str, core_type_path, needs_i64_cast};
9
10pub fn gen_from_core_to_binding(typ: &TypeDef, core_import: &str, opaque_types: &AHashSet<String>) -> String {
12 gen_from_core_to_binding_cfg(typ, core_import, opaque_types, &ConversionConfig::default())
13}
14
15pub fn gen_from_core_to_binding_cfg(
17 typ: &TypeDef,
18 core_import: &str,
19 opaque_types: &AHashSet<String>,
20 config: &ConversionConfig,
21) -> String {
22 let core_path = core_type_path(typ, core_import);
23 let binding_name = format!("{}{}", config.type_name_prefix, typ.name);
24 let mut out = String::with_capacity(256);
25 writeln!(out, "impl From<{core_path}> for {binding_name} {{").ok();
26 writeln!(out, " fn from(val: {core_path}) -> Self {{").ok();
27
28 if is_newtype(typ) {
30 let field = &typ.fields[0];
31 let inner_expr = match &field.ty {
32 TypeRef::Named(_) => "val.0.into()".to_string(),
33 TypeRef::Path => "val.0.to_string_lossy().to_string()".to_string(),
34 TypeRef::Duration => "val.0.as_millis() as u64".to_string(),
35 _ => "val.0".to_string(),
36 };
37 writeln!(out, " Self {{ _0: {inner_expr} }}").ok();
38 writeln!(out, " }}").ok();
39 write!(out, "}}").ok();
40 return out;
41 }
42
43 let optionalized = config.optionalize_defaults && typ.has_default;
44 writeln!(out, " Self {{").ok();
45 for field in &typ.fields {
46 if !config.exclude_types.is_empty()
48 && super::helpers::field_references_excluded_type(&field.ty, config.exclude_types)
49 {
50 continue;
51 }
52 let base_conversion = field_conversion_from_core_cfg(
53 &field.name,
54 &field.ty,
55 field.optional,
56 field.sanitized,
57 opaque_types,
58 config,
59 );
60 let base_conversion = if field.is_boxed && matches!(&field.ty, TypeRef::Named(_)) {
62 if field.optional {
63 let src = format!("{}: val.{}.map(Into::into)", field.name, field.name);
65 let dst = format!("{}: val.{}.map(|v| (*v).into())", field.name, field.name);
66 if base_conversion == src { dst } else { base_conversion }
67 } else {
68 base_conversion.replace(&format!("val.{}", field.name), &format!("(*val.{})", field.name))
70 }
71 } else {
72 base_conversion
73 };
74 let base_conversion = if field.newtype_wrapper.is_some() {
80 match &field.ty {
81 TypeRef::Optional(_) => {
82 base_conversion.replace(
84 &format!("val.{}", field.name),
85 &format!("val.{}.map(|v| v.0)", field.name),
86 )
87 }
88 TypeRef::Vec(_) => {
89 base_conversion.replace(
91 &format!("val.{}", field.name),
92 &format!("val.{}.iter().map(|v| v.0).collect::<Vec<_>>()", field.name),
93 )
94 }
95 _ if field.optional => base_conversion.replace(
98 &format!("val.{}", field.name),
99 &format!("val.{}.map(|v| v.0)", field.name),
100 ),
101 _ => {
102 base_conversion.replace(&format!("val.{}", field.name), &format!("val.{}.0", field.name))
104 }
105 }
106 } else {
107 base_conversion
108 };
109 let is_flattened_optional = field.optional && matches!(field.ty, TypeRef::Optional(_));
115 let base_conversion = if is_flattened_optional {
116 if let TypeRef::Optional(inner) = &field.ty {
117 let inner_conv = field_conversion_from_core_cfg(
119 &field.name,
120 inner.as_ref(),
121 true,
122 field.sanitized,
123 opaque_types,
124 config,
125 );
126 inner_conv.replace(&format!("val.{}", field.name), &format!("val.{}.flatten()", field.name))
128 } else {
129 base_conversion
130 }
131 } else {
132 base_conversion
133 };
134 let needs_some_wrap = !is_flattened_optional
138 && ((optionalized && !field.optional)
139 || (config.option_duration_on_defaults
140 && typ.has_default
141 && !field.optional
142 && matches!(field.ty, TypeRef::Duration)));
143 let conversion = if needs_some_wrap {
144 if let Some(expr) = base_conversion.strip_prefix(&format!("{}: ", field.name)) {
146 format!("{}: Some({})", field.name, expr)
147 } else {
148 base_conversion
149 }
150 } else {
151 base_conversion
152 };
153 let conversion = if !field.sanitized {
156 apply_core_wrapper_from_core(
157 &conversion,
158 &field.name,
159 &field.core_wrapper,
160 &field.vec_inner_core_wrapper,
161 field.optional,
162 )
163 } else {
164 conversion
165 };
166 if field.cfg.is_some() {
168 continue;
169 }
170 writeln!(out, " {conversion},").ok();
171 }
172
173 writeln!(out, " }}").ok();
174 writeln!(out, " }}").ok();
175 write!(out, "}}").ok();
176 out
177}
178
179pub fn field_conversion_from_core(
182 name: &str,
183 ty: &TypeRef,
184 optional: bool,
185 sanitized: bool,
186 opaque_types: &AHashSet<String>,
187) -> String {
188 if sanitized {
192 if let TypeRef::Vec(inner) = ty {
195 if matches!(inner.as_ref(), TypeRef::Primitive(_)) {
196 if optional {
197 return format!(
198 "{name}: val.{name}.map(|t| {{ let arr: Vec<_> = [t.0, t.1].into_iter().map(|v| v as _).collect(); arr }})"
199 );
200 }
201 return format!("{name}: vec![val.{name}.0 as _, val.{name}.1 as _]");
202 }
203 }
204 if let TypeRef::Optional(opt_inner) = ty {
206 if let TypeRef::Vec(vec_inner) = opt_inner.as_ref() {
207 if matches!(vec_inner.as_ref(), TypeRef::Primitive(_)) {
208 return format!("{name}: val.{name}.map(|t| vec![t.0 as _, t.1 as _])");
209 }
210 }
211 }
212 if let TypeRef::Map(k, v) = ty {
214 if matches!(k.as_ref(), TypeRef::String) && matches!(v.as_ref(), TypeRef::String) {
215 if optional {
216 return format!(
217 "{name}: val.{name}.as_ref().map(|m| m.iter().map(|(k, v)| (k.to_string(), v.to_string())).collect())"
218 );
219 }
220 return format!(
221 "{name}: val.{name}.into_iter().map(|(k, v)| (k.to_string(), v.to_string())).collect()"
222 );
223 }
224 }
225 if let TypeRef::Vec(inner) = ty {
228 if matches!(inner.as_ref(), TypeRef::String) {
229 if optional {
230 return format!(
231 "{name}: val.{name}.as_ref().map(|v| v.iter().map(|i| format!(\"{{:?}}\", i)).collect())"
232 );
233 }
234 return format!("{name}: val.{name}.iter().map(|i| format!(\"{{:?}}\", i)).collect()");
235 }
236 }
237 if let TypeRef::Optional(opt_inner) = ty {
239 if let TypeRef::Vec(vec_inner) = opt_inner.as_ref() {
240 if matches!(vec_inner.as_ref(), TypeRef::String) {
241 return format!(
242 "{name}: val.{name}.as_ref().map(|v| v.iter().map(|i| format!(\"{{:?}}\", i)).collect())"
243 );
244 }
245 }
246 }
247 if matches!(ty, TypeRef::String) {
251 if optional {
252 return format!("{name}: val.{name}.as_ref().map(|v| format!(\"{{v:?}}\"))");
253 }
254 return format!("{name}: format!(\"{{:?}}\", val.{name})");
255 }
256 if optional {
259 return format!("{name}: val.{name}.as_ref().map(|v| format!(\"{{v:?}}\"))");
260 }
261 return format!("{name}: format!(\"{{:?}}\", val.{name})");
262 }
263 match ty {
264 TypeRef::Duration => {
266 if optional {
267 return format!("{name}: val.{name}.map(|d| d.as_millis() as u64)");
268 }
269 format!("{name}: val.{name}.as_millis() as u64")
270 }
271 TypeRef::Path => {
273 if optional {
274 format!("{name}: val.{name}.map(|p| p.to_string_lossy().to_string())")
275 } else {
276 format!("{name}: val.{name}.to_string_lossy().to_string()")
277 }
278 }
279 TypeRef::Optional(inner) if matches!(inner.as_ref(), TypeRef::Path) => {
280 format!("{name}: val.{name}.map(|p| p.to_string_lossy().to_string())")
281 }
282 TypeRef::Char => {
284 if optional {
285 format!("{name}: val.{name}.map(|c| c.to_string())")
286 } else {
287 format!("{name}: val.{name}.to_string()")
288 }
289 }
290 TypeRef::Bytes => {
292 if optional {
293 format!("{name}: val.{name}.map(|v| v.to_vec())")
294 } else {
295 format!("{name}: val.{name}.to_vec()")
296 }
297 }
298 TypeRef::Named(n) if opaque_types.contains(n.as_str()) => {
300 if optional {
301 format!("{name}: val.{name}.map(|v| {n} {{ inner: Arc::new(v) }})")
302 } else {
303 format!("{name}: {n} {{ inner: Arc::new(val.{name}) }}")
304 }
305 }
306 TypeRef::Json => {
308 if optional {
309 format!("{name}: val.{name}.as_ref().map(ToString::to_string)")
310 } else {
311 format!("{name}: val.{name}.to_string()")
312 }
313 }
314 TypeRef::Optional(inner) if matches!(inner.as_ref(), TypeRef::Json) => {
315 format!("{name}: val.{name}.as_ref().map(ToString::to_string)")
316 }
317 TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Json) => {
318 if optional {
319 format!("{name}: val.{name}.as_ref().map(|v| v.iter().map(|i| i.to_string()).collect())")
320 } else {
321 format!("{name}: val.{name}.iter().map(ToString::to_string).collect()")
322 }
323 }
324 TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Optional(oi) if matches!(oi.as_ref(), TypeRef::Json)) => {
326 if optional {
327 format!(
328 "{name}: val.{name}.as_ref().map(|v| v.iter().map(|i| i.as_ref().map(ToString::to_string)).collect())"
329 )
330 } else {
331 format!("{name}: val.{name}.iter().map(|i| i.as_ref().map(ToString::to_string)).collect()")
332 }
333 }
334 TypeRef::Map(k, v) if matches!(v.as_ref(), TypeRef::Json) => {
336 let k_is_json = matches!(k.as_ref(), TypeRef::Json);
337 let k_expr = if k_is_json { "k.to_string()" } else { "k" };
338 if optional {
339 format!("{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| ({k_expr}, v.to_string())).collect())")
340 } else {
341 format!("{name}: val.{name}.into_iter().map(|(k, v)| ({k_expr}, v.to_string())).collect()")
342 }
343 }
344 TypeRef::Map(k, _v) if matches!(k.as_ref(), TypeRef::Json) => {
346 if optional {
347 format!("{name}: val.{name}.map(|m| m.into_iter().map(|(k, v)| (k.to_string(), v)).collect())")
348 } else {
349 format!("{name}: val.{name}.into_iter().map(|(k, v)| (k.to_string(), v)).collect()")
350 }
351 }
352 _ => field_conversion_to_core(name, ty, optional),
354 }
355}
356
357pub fn field_conversion_from_core_cfg(
359 name: &str,
360 ty: &TypeRef,
361 optional: bool,
362 sanitized: bool,
363 opaque_types: &AHashSet<String>,
364 config: &ConversionConfig,
365) -> String {
366 if sanitized {
371 if config.map_uses_jsvalue {
372 if let TypeRef::Map(k, v) = ty {
374 if matches!(k.as_ref(), TypeRef::String) && matches!(v.as_ref(), TypeRef::String) {
375 if optional {
376 return format!(
377 "{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::to_value(v).ok())"
378 );
379 }
380 return format!("{name}: serde_wasm_bindgen::to_value(&val.{name}).unwrap_or(JsValue::NULL)");
381 }
382 }
383 if let TypeRef::Vec(inner) = ty {
385 if matches!(inner.as_ref(), TypeRef::Json) {
386 if optional {
387 return format!(
388 "{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::to_value(v).ok())"
389 );
390 }
391 return format!("{name}: serde_wasm_bindgen::to_value(&val.{name}).unwrap_or(JsValue::NULL)");
392 }
393 }
394 }
395 return field_conversion_from_core(name, ty, optional, sanitized, opaque_types);
396 }
397
398 if config.vec_named_to_string {
402 if let TypeRef::Vec(inner) = ty {
403 if matches!(inner.as_ref(), TypeRef::Named(_)) {
404 if optional {
405 return format!("{name}: val.{name}.as_ref().and_then(|v| serde_json::to_string(v).ok())");
406 }
407 return format!("{name}: serde_json::to_string(&val.{name}).unwrap_or_default()");
408 }
409 }
410 }
411
412 if config.map_uses_jsvalue {
414 let is_nested_vec = matches!(ty, TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Vec(_)));
415 let is_map = matches!(ty, TypeRef::Map(_, _));
416 if is_nested_vec || is_map {
417 if optional {
418 return format!("{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::to_value(v).ok())");
419 }
420 return format!("{name}: serde_wasm_bindgen::to_value(&val.{name}).unwrap_or(JsValue::NULL)");
421 }
422 if let TypeRef::Optional(inner) = ty {
423 let is_inner_nested = matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Vec(_)));
424 let is_inner_map = matches!(inner.as_ref(), TypeRef::Map(_, _));
425 if is_inner_nested || is_inner_map {
426 return format!("{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::to_value(v).ok())");
427 }
428 }
429 }
430
431 let prefix = config.type_name_prefix;
432 let is_enum_string = |n: &str| -> bool { config.enum_string_names.as_ref().is_some_and(|names| names.contains(n)) };
433
434 match ty {
435 TypeRef::Primitive(p) if config.cast_large_ints_to_i64 && needs_i64_cast(p) => {
437 let cast_to = binding_prim_str(p);
438 if optional {
439 format!("{name}: val.{name}.map(|v| v as {cast_to})")
440 } else {
441 format!("{name}: val.{name} as {cast_to}")
442 }
443 }
444 TypeRef::Optional(inner)
446 if config.cast_large_ints_to_i64
447 && matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
448 {
449 if let TypeRef::Primitive(p) = inner.as_ref() {
450 let cast_to = binding_prim_str(p);
451 format!("{name}: val.{name}.map(|v| v as {cast_to})")
452 } else {
453 field_conversion_from_core(name, ty, optional, sanitized, opaque_types)
454 }
455 }
456 TypeRef::Primitive(PrimitiveType::F32) if config.cast_f32_to_f64 => {
458 if optional {
459 format!("{name}: val.{name}.map(|v| v as f64)")
460 } else {
461 format!("{name}: val.{name} as f64")
462 }
463 }
464 TypeRef::Duration if config.cast_large_ints_to_i64 => {
466 if optional {
467 format!("{name}: val.{name}.map(|d| d.as_millis() as u64 as i64)")
468 } else {
469 format!("{name}: val.{name}.as_millis() as u64 as i64")
470 }
471 }
472 TypeRef::Named(n) if opaque_types.contains(n.as_str()) && !prefix.is_empty() => {
474 let prefixed = format!("{prefix}{n}");
475 if optional {
476 format!("{name}: val.{name}.map(|v| {prefixed} {{ inner: Arc::new(v) }})")
477 } else {
478 format!("{name}: {prefixed} {{ inner: Arc::new(val.{name}) }}")
479 }
480 }
481 TypeRef::Named(n) if is_enum_string(n) => {
483 if optional {
486 format!(
487 "{name}: val.{name}.as_ref().map(|v| serde_json::to_value(v).ok().and_then(|s| s.as_str().map(String::from)).unwrap_or_default())"
488 )
489 } else {
490 format!(
491 "{name}: serde_json::to_value(val.{name}).ok().and_then(|s| s.as_str().map(String::from)).unwrap_or_default()"
492 )
493 }
494 }
495 TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Named(n) if is_enum_string(n)) => {
497 if optional {
498 format!(
499 "{name}: val.{name}.as_ref().map(|v| v.iter().map(|x| serde_json::to_value(x).ok().and_then(|s| s.as_str().map(String::from)).unwrap_or_default()).collect())"
500 )
501 } else {
502 format!(
503 "{name}: val.{name}.iter().map(|v| serde_json::to_value(v).ok().and_then(|s| s.as_str().map(String::from)).unwrap_or_default()).collect()"
504 )
505 }
506 }
507 TypeRef::Optional(inner) if matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Named(n) if is_enum_string(n))) =>
509 {
510 format!(
511 "{name}: val.{name}.as_ref().map(|v| v.iter().map(|x| serde_json::to_value(x).ok().and_then(|s| s.as_str().map(String::from)).unwrap_or_default()).collect())"
512 )
513 }
514 TypeRef::Vec(inner)
516 if config.cast_f32_to_f64 && matches!(inner.as_ref(), TypeRef::Primitive(PrimitiveType::F32)) =>
517 {
518 if optional {
519 format!("{name}: val.{name}.as_ref().map(|v| v.iter().map(|&x| x as f64).collect())")
520 } else {
521 format!("{name}: val.{name}.iter().map(|&v| v as f64).collect()")
522 }
523 }
524 TypeRef::Optional(inner)
526 if config.cast_f32_to_f64
527 && matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Primitive(PrimitiveType::F32))) =>
528 {
529 format!("{name}: val.{name}.as_ref().map(|v| v.iter().map(|&x| x as f64).collect())")
530 }
531 TypeRef::Optional(inner)
533 if config.cast_large_ints_to_i64
534 && matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p))) =>
535 {
536 if let TypeRef::Vec(vi) = inner.as_ref() {
537 if let TypeRef::Primitive(p) = vi.as_ref() {
538 let cast_to = binding_prim_str(p);
539 if sanitized {
540 format!("{name}: val.{name}.map(|(a, b)| vec![a as {cast_to}, b as {cast_to}])")
542 } else {
543 format!("{name}: val.{name}.as_ref().map(|v| v.iter().map(|&x| x as {cast_to}).collect())")
544 }
545 } else {
546 field_conversion_from_core(name, ty, optional, sanitized, opaque_types)
547 }
548 } else {
549 field_conversion_from_core(name, ty, optional, sanitized, opaque_types)
550 }
551 }
552 TypeRef::Vec(outer)
554 if config.cast_f32_to_f64
555 && matches!(outer.as_ref(), TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Primitive(PrimitiveType::F32))) =>
556 {
557 if optional {
558 format!(
559 "{name}: val.{name}.as_ref().map(|v| v.iter().map(|inner| inner.iter().map(|&x| x as f64).collect()).collect())"
560 )
561 } else {
562 format!("{name}: val.{name}.iter().map(|inner| inner.iter().map(|&x| x as f64).collect()).collect()")
563 }
564 }
565 TypeRef::Optional(inner)
567 if config.cast_f32_to_f64
568 && matches!(inner.as_ref(), TypeRef::Vec(outer) if matches!(outer.as_ref(), TypeRef::Vec(prim) if matches!(prim.as_ref(), TypeRef::Primitive(PrimitiveType::F32)))) =>
569 {
570 format!(
571 "{name}: val.{name}.as_ref().map(|v| v.iter().map(|inner| inner.iter().map(|&x| x as f64).collect()).collect())"
572 )
573 }
574 TypeRef::Optional(inner)
576 if config.cast_large_ints_to_i64
577 && matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
578 {
579 if let TypeRef::Primitive(p) = inner.as_ref() {
580 let cast_to = binding_prim_str(p);
581 format!("{name}: val.{name}.map(|v| v as {cast_to})")
582 } else {
583 field_conversion_from_core(name, ty, optional, sanitized, opaque_types)
584 }
585 }
586 TypeRef::Map(_k, v)
588 if config.cast_large_ints_to_i64 && matches!(v.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
589 {
590 if let TypeRef::Primitive(p) = v.as_ref() {
591 let cast_to = binding_prim_str(p);
592 if optional {
593 format!(
594 "{name}: val.{name}.as_ref().map(|m| m.iter().map(|(k, v)| (k.clone(), *v as {cast_to})).collect())"
595 )
596 } else {
597 format!("{name}: val.{name}.iter().map(|(k, v)| (k.clone(), *v as {cast_to})).collect()")
598 }
599 } else {
600 field_conversion_from_core(name, ty, optional, sanitized, opaque_types)
601 }
602 }
603 TypeRef::Vec(inner)
605 if config.cast_large_ints_to_i64
606 && matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p)) =>
607 {
608 if let TypeRef::Primitive(p) = inner.as_ref() {
609 let cast_to = binding_prim_str(p);
610 if sanitized {
611 if optional {
613 format!("{name}: val.{name}.map(|(a, b)| vec![a as {cast_to}, b as {cast_to}])")
614 } else {
615 format!("{name}: {{ let (a, b) = val.{name}; vec![a as {cast_to}, b as {cast_to}] }}")
616 }
617 } else if optional {
618 format!("{name}: val.{name}.as_ref().map(|v| v.iter().map(|&x| x as {cast_to}).collect())")
619 } else {
620 format!("{name}: val.{name}.iter().map(|&v| v as {cast_to}).collect()")
621 }
622 } else {
623 field_conversion_from_core(name, ty, optional, sanitized, opaque_types)
624 }
625 }
626 TypeRef::Vec(outer)
628 if config.cast_large_ints_to_i64
629 && matches!(outer.as_ref(), TypeRef::Vec(inner) if matches!(inner.as_ref(), TypeRef::Primitive(p) if needs_i64_cast(p))) =>
630 {
631 if let TypeRef::Vec(inner) = outer.as_ref() {
632 if let TypeRef::Primitive(p) = inner.as_ref() {
633 let cast_to = binding_prim_str(p);
634 if optional {
635 format!(
636 "{name}: val.{name}.as_ref().map(|v| v.iter().map(|inner| inner.iter().map(|&x| x as {cast_to}).collect()).collect())"
637 )
638 } else {
639 format!(
640 "{name}: val.{name}.iter().map(|inner| inner.iter().map(|&x| x as {cast_to}).collect()).collect()"
641 )
642 }
643 } else {
644 field_conversion_from_core(name, ty, optional, sanitized, opaque_types)
645 }
646 } else {
647 field_conversion_from_core(name, ty, optional, sanitized, opaque_types)
648 }
649 }
650 TypeRef::Json if config.json_to_string => {
652 if optional {
653 format!("{name}: val.{name}.as_ref().map(ToString::to_string)")
654 } else {
655 format!("{name}: val.{name}.to_string()")
656 }
657 }
658 TypeRef::Json if config.map_uses_jsvalue => {
660 if optional {
661 format!("{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::to_value(v).ok())")
662 } else {
663 format!("{name}: serde_wasm_bindgen::to_value(&val.{name}).unwrap_or(JsValue::NULL)")
664 }
665 }
666 TypeRef::Vec(inner) if config.map_uses_jsvalue && matches!(inner.as_ref(), TypeRef::Json) => {
668 if optional {
669 format!("{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::to_value(v).ok())")
670 } else {
671 format!("{name}: serde_wasm_bindgen::to_value(&val.{name}).unwrap_or(JsValue::NULL)")
672 }
673 }
674 TypeRef::Optional(inner)
676 if config.map_uses_jsvalue
677 && matches!(inner.as_ref(), TypeRef::Vec(vi) if matches!(vi.as_ref(), TypeRef::Json)) =>
678 {
679 format!("{name}: val.{name}.as_ref().and_then(|v| serde_wasm_bindgen::to_value(v).ok())")
680 }
681 _ => field_conversion_from_core(name, ty, optional, sanitized, opaque_types),
683 }
684}
685
686fn apply_core_wrapper_from_core(
689 conversion: &str,
690 name: &str,
691 core_wrapper: &CoreWrapper,
692 vec_inner_core_wrapper: &CoreWrapper,
693 optional: bool,
694) -> String {
695 if *vec_inner_core_wrapper == CoreWrapper::Arc {
697 return conversion
698 .replace(".map(Into::into).collect()", ".map(|v| (*v).clone().into()).collect()")
699 .replace(
700 "map(|v| v.into_iter().map(Into::into)",
701 "map(|v| v.into_iter().map(|v| (*v).clone().into())",
702 );
703 }
704
705 match core_wrapper {
706 CoreWrapper::None => conversion.to_string(),
707 CoreWrapper::Cow => {
708 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
713 if optional {
714 conversion.to_string()
716 } else if expr == format!("val.{name}") {
717 format!("{name}: val.{name}.into_owned()")
718 } else {
719 conversion.to_string()
720 }
721 } else {
722 conversion.to_string()
723 }
724 }
725 CoreWrapper::Arc => {
726 if conversion.contains("{ inner: Arc::new(") {
735 return conversion.replace("{ inner: Arc::new(v) }", "{ inner: v }").replace(
736 &format!("{{ inner: Arc::new(val.{name}) }}"),
737 &format!("{{ inner: val.{name} }}"),
738 );
739 }
740 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
741 if optional {
742 format!("{name}: {expr}.map(|v| (*v).clone().into())")
743 } else {
744 let unwrapped = expr.replace(&format!("val.{name}"), &format!("(*val.{name}).clone()"));
745 format!("{name}: {unwrapped}")
746 }
747 } else {
748 conversion.to_string()
749 }
750 }
751 CoreWrapper::Bytes => {
752 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
754 if optional {
755 format!("{name}: {expr}.map(|v| v.to_vec())")
756 } else if expr == format!("val.{name}") {
757 format!("{name}: val.{name}.to_vec()")
758 } else {
759 conversion.to_string()
760 }
761 } else {
762 conversion.to_string()
763 }
764 }
765 CoreWrapper::ArcMutex => {
766 if let Some(expr) = conversion.strip_prefix(&format!("{name}: ")) {
768 if optional {
769 format!("{name}: {expr}.map(|v| v.lock().unwrap().clone().into())")
770 } else if expr == format!("val.{name}") {
771 format!("{name}: val.{name}.lock().unwrap().clone().into()")
772 } else {
773 conversion.to_string()
774 }
775 } else {
776 conversion.to_string()
777 }
778 }
779 }
780}