1use std::sync::Arc;
41
42#[crate::polydat_node(category = Conversions)]
59fn __u64_to_u32(n: u64) -> u32 {
60 if n > u32::MAX as u64 {
61 panic!("__u64_to_u32: value {n} exceeds u32::MAX ({})", u32::MAX);
62 }
63 n as u32
64}
65
66#[crate::polydat_node(category = Conversions)]
67fn __u64_to_i64(n: u64) -> i64 {
68 if n > i64::MAX as u64 {
69 panic!("__u64_to_i64: value {n} exceeds i64::MAX ({})", i64::MAX);
70 }
71 n as i64
72}
73
74#[crate::polydat_node(category = Conversions)]
75fn __u64_to_i32(n: u64) -> i32 {
76 if n > i32::MAX as u64 {
77 panic!("__u64_to_i32: value {n} exceeds i32::MAX ({})", i32::MAX);
78 }
79 n as i32
80}
81
82#[crate::polydat_node(category = Conversions)]
83fn __u64_to_f32(n: u64) -> f32 {
84 n as f32
88}
89
90#[crate::polydat_node(category = Conversions)]
91fn __u32_to_i32(n: u32) -> i32 {
92 if n > i32::MAX as u32 {
93 panic!("__u32_to_i32: value {n} exceeds i32::MAX ({})", i32::MAX);
94 }
95 n as i32
96}
97
98#[crate::polydat_node(category = Conversions)]
99fn __u32_to_f32(n: u32) -> f32 {
100 n as f32
101}
102
103#[crate::polydat_node(category = Conversions)]
104fn __i64_to_u64(n: i64) -> u64 {
105 if n < 0 {
106 panic!("__i64_to_u64: negative value {n} cannot be represented as u64");
107 }
108 n as u64
109}
110
111#[crate::polydat_node(category = Conversions)]
112fn __i64_to_u32(n: i64) -> u32 {
113 if n < 0 || n > u32::MAX as i64 {
114 panic!("__i64_to_u32: value {n} out of u32 range [0, {}]", u32::MAX);
115 }
116 n as u32
117}
118
119#[crate::polydat_node(category = Conversions)]
120fn __i64_to_i32(n: i64) -> i32 {
121 if n < i32::MIN as i64 || n > i32::MAX as i64 {
122 panic!(
123 "__i64_to_i32: value {n} out of i32 range [{}, {}]",
124 i32::MIN,
125 i32::MAX
126 );
127 }
128 n as i32
129}
130
131#[crate::polydat_node(category = Conversions)]
132fn __i64_to_f32(n: i64) -> f32 {
133 n as f32
134}
135
136#[crate::polydat_node(category = Conversions)]
137fn __i32_to_u64(n: i32) -> u64 {
138 if n < 0 {
139 panic!("__i32_to_u64: negative value {n} cannot be represented as u64");
140 }
141 n as u64
142}
143
144#[crate::polydat_node(category = Conversions)]
145fn __i32_to_u32(n: i32) -> u32 {
146 if n < 0 {
147 panic!("__i32_to_u32: negative value {n} cannot be represented as u32");
148 }
149 n as u32
150}
151
152#[crate::polydat_node(category = Conversions)]
153fn __i32_to_f32(n: i32) -> f32 {
154 n as f32
155}
156
157#[crate::polydat_node(category = Conversions)]
158fn __f64_to_u64_checked(f: f64) -> u64 {
159 if !f.is_finite() {
160 panic!("__f64_to_u64_checked: non-finite value {f} cannot be represented as u64");
161 }
162 let n = f.trunc();
163 if n < 0.0 || n > u64::MAX as f64 {
164 panic!(
165 "__f64_to_u64_checked: value {f} out of u64 range [0, {}]",
166 u64::MAX
167 );
168 }
169 n as u64
170}
171
172#[crate::polydat_node(category = Conversions)]
173fn __f64_to_u32(f: f64) -> u32 {
174 if !f.is_finite() {
175 panic!("__f64_to_u32: non-finite value {f} cannot be represented as u32");
176 }
177 let n = f.trunc();
178 if n < 0.0 || n > u32::MAX as f64 {
179 panic!("__f64_to_u32: value {f} out of u32 range [0, {}]", u32::MAX);
180 }
181 n as u32
182}
183
184#[crate::polydat_node(category = Conversions)]
185fn __f64_to_i64(f: f64) -> i64 {
186 if !f.is_finite() {
187 panic!("__f64_to_i64: non-finite value {f} cannot be represented as i64");
188 }
189 let n = f.trunc();
190 if n < i64::MIN as f64 || n > i64::MAX as f64 {
191 panic!(
192 "__f64_to_i64: value {f} out of i64 range [{}, {}]",
193 i64::MIN,
194 i64::MAX
195 );
196 }
197 n as i64
198}
199
200#[crate::polydat_node(category = Conversions)]
201fn __f64_to_i32(f: f64) -> i32 {
202 if !f.is_finite() {
203 panic!("__f64_to_i32: non-finite value {f} cannot be represented as i32");
204 }
205 let n = f.trunc();
206 if n < i32::MIN as f64 || n > i32::MAX as f64 {
207 panic!(
208 "__f64_to_i32: value {f} out of i32 range [{}, {}]",
209 i32::MIN,
210 i32::MAX
211 );
212 }
213 n as i32
214}
215
216#[crate::polydat_node(category = Conversions)]
217fn __f64_to_f32(f: f64) -> f32 {
218 f as f32
221}
222
223#[crate::polydat_node(category = Conversions)]
224fn __f32_to_u64(f: f32) -> u64 {
225 if !f.is_finite() {
226 panic!("__f32_to_u64: non-finite value {f} cannot be represented as u64");
227 }
228 let n = f.trunc();
229 if n < 0.0 || n > u64::MAX as f32 {
230 panic!("__f32_to_u64: value {f} out of u64 range [0, {}]", u64::MAX);
231 }
232 n as u64
233}
234
235#[crate::polydat_node(category = Conversions)]
236fn __f32_to_u32(f: f32) -> u32 {
237 if !f.is_finite() {
238 panic!("__f32_to_u32: non-finite value {f} cannot be represented as u32");
239 }
240 let n = f.trunc();
241 if n < 0.0 || n > u32::MAX as f32 {
242 panic!("__f32_to_u32: value {f} out of u32 range [0, {}]", u32::MAX);
243 }
244 n as u32
245}
246
247#[crate::polydat_node(category = Conversions)]
248fn __f32_to_i64(f: f32) -> i64 {
249 if !f.is_finite() {
250 panic!("__f32_to_i64: non-finite value {f} cannot be represented as i64");
251 }
252 let n = f.trunc();
253 if n < i64::MIN as f32 || n > i64::MAX as f32 {
254 panic!(
255 "__f32_to_i64: value {f} out of i64 range [{}, {}]",
256 i64::MIN,
257 i64::MAX
258 );
259 }
260 n as i64
261}
262
263#[crate::polydat_node(category = Conversions)]
264fn __f32_to_i32(f: f32) -> i32 {
265 if !f.is_finite() {
266 panic!("__f32_to_i32: non-finite value {f} cannot be represented as i32");
267 }
268 let n = f.trunc();
269 if n < i32::MIN as f32 || n > i32::MAX as f32 {
270 panic!(
271 "__f32_to_i32: value {f} out of i32 range [{}, {}]",
272 i32::MIN,
273 i32::MAX
274 );
275 }
276 n as i32
277}
278
279#[crate::polydat_node(category = Conversions)]
284fn __bool_to_u32(b: bool) -> u32 {
285 if b { 1 } else { 0 }
286}
287
288#[crate::polydat_node(category = Conversions)]
289fn __bool_to_i64(b: bool) -> i64 {
290 if b { 1 } else { 0 }
291}
292
293#[crate::polydat_node(category = Conversions)]
294fn __bool_to_i32(b: bool) -> i32 {
295 if b { 1 } else { 0 }
296}
297
298#[crate::polydat_node(category = Conversions)]
299fn __bool_to_f64(b: bool) -> f64 {
300 if b { 1.0 } else { 0.0 }
301}
302
303#[crate::polydat_node(category = Conversions)]
304fn __bool_to_f32(b: bool) -> f32 {
305 if b { 1.0 } else { 0.0 }
306}
307
308#[crate::polydat_node(category = Conversions)]
309fn __u32_to_bool(n: u32) -> bool {
310 n != 0
311}
312
313#[crate::polydat_node(category = Conversions)]
314fn __i64_to_bool(n: i64) -> bool {
315 n != 0
316}
317
318#[crate::polydat_node(category = Conversions)]
319fn __i32_to_bool(n: i32) -> bool {
320 n != 0
321}
322
323#[crate::polydat_node(category = Conversions)]
324fn __f64_to_bool(f: f64) -> bool {
325 f != 0.0 && !f.is_nan()
326}
327
328#[crate::polydat_node(category = Conversions)]
329fn __f32_to_bool(f: f32) -> bool {
330 f != 0.0 && !f.is_nan()
331}
332
333#[crate::polydat_node(category = Conversions)]
342fn __str_to_u32(input: &str) -> u32 {
343 let raw = input.trim();
344 raw.parse::<u32>()
345 .unwrap_or_else(|e| panic!("__str_to_u32: cannot parse {raw:?} as u32: {e}"))
346}
347
348pub(crate) fn parse_i64(input: &str) -> i64 {
351 let raw = input.trim();
352 raw.parse::<i64>()
353 .unwrap_or_else(|e| panic!("__str_to_i64: cannot parse {raw:?} as i64: {e}"))
354}
355
356#[crate::polydat_node(category = Conversions)]
357fn __str_to_i64(input: &str) -> i64 {
358 parse_i64(input)
359}
360
361#[crate::polydat_node(category = Conversions)]
362fn __str_to_i32(input: &str) -> i32 {
363 let raw = input.trim();
364 raw.parse::<i32>()
365 .unwrap_or_else(|e| panic!("__str_to_i32: cannot parse {raw:?} as i32: {e}"))
366}
367
368#[crate::polydat_node(category = Conversions)]
369fn __str_to_f32(input: &str) -> f32 {
370 let raw = input.trim();
371 raw.parse::<f32>()
372 .unwrap_or_else(|e| panic!("__str_to_f32: cannot parse {raw:?} as f32: {e}"))
373}
374
375#[crate::polydat_node(category = Conversions)]
376fn __str_to_bytes(input: &str) -> Vec<u8> {
377 let raw = input.trim();
378 data_encoding::HEXLOWER_PERMISSIVE
379 .decode(raw.as_bytes())
380 .unwrap_or_else(|e| panic!("__str_to_bytes: cannot hex-decode {raw:?}: {e}"))
381}
382
383#[crate::polydat_node(category = Conversions)]
384fn __str_to_json(input: &str) -> Arc<serde_json::Value> {
385 match serde_json::from_str::<serde_json::Value>(input) {
391 Ok(parsed) => Arc::new(parsed),
392 Err(e) => {
393 let wrapped = serde_json::json!({
394 "error": "invalid JSON",
395 "message": e.to_string(),
396 "raw": input,
397 });
398 Arc::new(wrapped)
399 }
400 }
401}
402
403#[crate::polydat_node(category = Conversions)]
404fn __str_to_vec_f32(input: &str) -> Vec<f32> {
405 let raw = input.trim();
406 let parsed: serde_json::Value = serde_json::from_str(raw)
407 .unwrap_or_else(|e| panic!("__str_to_vec_f32: cannot parse {raw:?} as JSON array: {e}"));
408 let arr = parsed
409 .as_array()
410 .unwrap_or_else(|| panic!("__str_to_vec_f32: parsed JSON is not an array: {raw:?}"));
411 arr.iter()
412 .map(|j| {
413 j.as_f64().unwrap_or_else(|| {
414 panic!("__str_to_vec_f32: element {j:?} is not a number in {raw:?}")
415 }) as f32
416 })
417 .collect()
418}
419
420#[crate::polydat_node(category = Conversions)]
421fn __str_to_vec_i32(input: &str) -> Vec<i32> {
422 let raw = input.trim();
423 let parsed: serde_json::Value = serde_json::from_str(raw)
424 .unwrap_or_else(|e| panic!("__str_to_vec_i32: cannot parse {raw:?} as JSON array: {e}"));
425 let arr = parsed
426 .as_array()
427 .unwrap_or_else(|| panic!("__str_to_vec_i32: parsed JSON is not an array: {raw:?}"));
428 arr.iter()
429 .map(|j| {
430 let n = j.as_i64().unwrap_or_else(|| {
431 panic!("__str_to_vec_i32: element {j:?} is not an integer in {raw:?}")
432 });
433 if !(i32::MIN as i64..=i32::MAX as i64).contains(&n) {
434 panic!(
435 "__str_to_vec_i32: element {n} out of i32 range [{}, {}]",
436 i32::MIN,
437 i32::MAX
438 );
439 }
440 n as i32
441 })
442 .collect()
443}
444
445#[crate::polydat_node(category = Conversions)]
461fn __u64_to_bytes(n: u64) -> Vec<u8> {
462 n.to_le_bytes().to_vec()
463}
464
465#[crate::polydat_node(category = Conversions)]
466fn __u32_to_bytes(n: u32) -> Vec<u8> {
467 n.to_le_bytes().to_vec()
468}
469
470#[crate::polydat_node(category = Conversions)]
471fn __i64_to_bytes(n: i64) -> Vec<u8> {
472 n.to_le_bytes().to_vec()
473}
474
475#[crate::polydat_node(category = Conversions)]
476fn __i32_to_bytes(n: i32) -> Vec<u8> {
477 n.to_le_bytes().to_vec()
478}
479
480#[crate::polydat_node(category = Conversions)]
481fn __f64_to_bytes(f: f64) -> Vec<u8> {
482 f.to_le_bytes().to_vec()
483}
484
485#[crate::polydat_node(category = Conversions)]
486fn __f32_to_bytes(f: f32) -> Vec<u8> {
487 f.to_le_bytes().to_vec()
488}
489
490#[crate::polydat_node(category = Conversions)]
491fn __bool_to_bytes(b: bool) -> Vec<u8> {
492 vec![if b { 1 } else { 0 }]
493}
494
495#[crate::polydat_node(category = Conversions)]
496fn __bytes_to_u64(b: &[u8]) -> u64 {
497 if b.len() != 8 {
498 panic!(
499 "__bytes_to_u64: expected exactly 8 bytes for u64, got {}",
500 b.len()
501 );
502 }
503 u64::from_le_bytes(b.try_into().unwrap())
504}
505
506#[crate::polydat_node(category = Conversions)]
507fn __bytes_to_u32(b: &[u8]) -> u32 {
508 if b.len() != 4 {
509 panic!(
510 "__bytes_to_u32: expected exactly 4 bytes for u32, got {}",
511 b.len()
512 );
513 }
514 u32::from_le_bytes(b.try_into().unwrap())
515}
516
517#[crate::polydat_node(category = Conversions)]
518fn __bytes_to_i64(b: &[u8]) -> i64 {
519 if b.len() != 8 {
520 panic!(
521 "__bytes_to_i64: expected exactly 8 bytes for i64, got {}",
522 b.len()
523 );
524 }
525 i64::from_le_bytes(b.try_into().unwrap())
526}
527
528#[crate::polydat_node(category = Conversions)]
529fn __bytes_to_i32(b: &[u8]) -> i32 {
530 if b.len() != 4 {
531 panic!(
532 "__bytes_to_i32: expected exactly 4 bytes for i32, got {}",
533 b.len()
534 );
535 }
536 i32::from_le_bytes(b.try_into().unwrap())
537}
538
539#[crate::polydat_node(category = Conversions)]
540fn __bytes_to_f64(b: &[u8]) -> f64 {
541 if b.len() != 8 {
542 panic!(
543 "__bytes_to_f64: expected exactly 8 bytes for f64, got {}",
544 b.len()
545 );
546 }
547 f64::from_le_bytes(b.try_into().unwrap())
548}
549
550#[crate::polydat_node(category = Conversions)]
551fn __bytes_to_f32(b: &[u8]) -> f32 {
552 if b.len() != 4 {
553 panic!(
554 "__bytes_to_f32: expected exactly 4 bytes for f32, got {}",
555 b.len()
556 );
557 }
558 f32::from_le_bytes(b.try_into().unwrap())
559}
560
561#[crate::polydat_node(category = Conversions)]
562fn __bytes_to_bool(b: &[u8]) -> bool {
563 if b.len() != 1 {
564 panic!(
565 "__bytes_to_bool: expected exactly 1 byte for bool, got {}",
566 b.len()
567 );
568 }
569 b[0] != 0
570}
571
572#[crate::polydat_node(category = Conversions)]
573fn __bytes_to_str(b: &[u8]) -> String {
574 data_encoding::HEXLOWER.encode(b)
575}
576
577#[crate::polydat_node(category = Conversions)]
578fn __bytes_to_json(b: &[u8]) -> Arc<serde_json::Value> {
579 let hex = data_encoding::HEXLOWER.encode(b);
580 Arc::new(serde_json::Value::String(hex))
581}
582
583#[crate::polydat_node(category = Conversions)]
584fn __bytes_to_vec_f32(b: &[u8]) -> Vec<f32> {
585 if !b.len().is_multiple_of(4) {
586 panic!(
587 "__bytes_to_vec_f32: byte length {} is not a multiple of 4 (f32 size)",
588 b.len()
589 );
590 }
591 b.as_chunks::<4>()
592 .0
593 .iter()
594 .map(|c| f32::from_le_bytes(*c))
595 .collect()
596}
597
598#[crate::polydat_node(category = Conversions)]
599fn __bytes_to_vec_i32(b: &[u8]) -> Vec<i32> {
600 if !b.len().is_multiple_of(4) {
601 panic!(
602 "__bytes_to_vec_i32: byte length {} is not a multiple of 4 (i32 size)",
603 b.len()
604 );
605 }
606 b.as_chunks::<4>()
607 .0
608 .iter()
609 .map(|c| i32::from_le_bytes(*c))
610 .collect()
611}
612
613#[crate::polydat_node(category = Conversions)]
622fn __u64_to_json(n: u64) -> Arc<serde_json::Value> {
623 Arc::new(serde_json::Value::from(n))
624}
625
626#[crate::polydat_node(category = Conversions)]
627fn __u32_to_json(n: u32) -> Arc<serde_json::Value> {
628 Arc::new(serde_json::Value::from(n))
629}
630
631#[crate::polydat_node(category = Conversions)]
632fn __i64_to_json(n: i64) -> Arc<serde_json::Value> {
633 Arc::new(serde_json::Value::from(n))
634}
635
636#[crate::polydat_node(category = Conversions)]
637fn __i32_to_json(n: i32) -> Arc<serde_json::Value> {
638 Arc::new(serde_json::Value::from(n))
639}
640
641#[crate::polydat_node(category = Conversions)]
642fn __f64_to_json(f: f64) -> Arc<serde_json::Value> {
643 let n = serde_json::Number::from_f64(f).unwrap_or_else(|| {
644 panic!("__f64_to_json: non-finite f64 {f} not representable as JSON number")
645 });
646 Arc::new(serde_json::Value::Number(n))
647}
648
649#[crate::polydat_node(category = Conversions)]
650fn __f32_to_json(f: f32) -> Arc<serde_json::Value> {
651 let n = serde_json::Number::from_f64(f as f64).unwrap_or_else(|| {
652 panic!("__f32_to_json: non-finite f32 {f} not representable as JSON number")
653 });
654 Arc::new(serde_json::Value::Number(n))
655}
656
657#[crate::polydat_node(category = Conversions)]
658fn __bool_to_json(b: bool) -> Arc<serde_json::Value> {
659 Arc::new(serde_json::Value::Bool(b))
660}
661
662#[crate::polydat_node(category = Conversions)]
663fn __json_to_u64(j: &serde_json::Value) -> u64 {
664 j.as_u64()
665 .unwrap_or_else(|| panic!("__json_to_u64: JSON value {j} is not a u64"))
666}
667
668#[crate::polydat_node(category = Conversions)]
669fn __json_to_u32(j: &serde_json::Value) -> u32 {
670 let n = j
671 .as_u64()
672 .unwrap_or_else(|| panic!("__json_to_u32: JSON value {j} is not a u64"));
673 if n > u32::MAX as u64 {
674 panic!("__json_to_u32: value {n} exceeds u32::MAX ({})", u32::MAX);
675 }
676 n as u32
677}
678
679#[crate::polydat_node(category = Conversions)]
680fn __json_to_i64(j: &serde_json::Value) -> i64 {
681 j.as_i64()
682 .unwrap_or_else(|| panic!("__json_to_i64: JSON value {j} is not an i64"))
683}
684
685#[crate::polydat_node(category = Conversions)]
686fn __json_to_i32(j: &serde_json::Value) -> i32 {
687 let n = j
688 .as_i64()
689 .unwrap_or_else(|| panic!("__json_to_i32: JSON value {j} is not an i64"));
690 if !(i32::MIN as i64..=i32::MAX as i64).contains(&n) {
691 panic!(
692 "__json_to_i32: value {n} out of i32 range [{}, {}]",
693 i32::MIN,
694 i32::MAX
695 );
696 }
697 n as i32
698}
699
700#[crate::polydat_node(category = Conversions)]
701fn __json_to_f64(j: &serde_json::Value) -> f64 {
702 j.as_f64()
703 .unwrap_or_else(|| panic!("__json_to_f64: JSON value {j} is not an f64"))
704}
705
706#[crate::polydat_node(category = Conversions)]
707fn __json_to_f32(j: &serde_json::Value) -> f32 {
708 let f = j
709 .as_f64()
710 .unwrap_or_else(|| panic!("__json_to_f32: JSON value {j} is not an f64"));
711 f as f32
712}
713
714#[crate::polydat_node(category = Conversions)]
715fn __json_to_bool(j: &serde_json::Value) -> bool {
716 j.as_bool()
717 .unwrap_or_else(|| panic!("__json_to_bool: JSON value {j} is not a bool"))
718}
719
720#[crate::polydat_node(category = Conversions)]
721fn __json_to_bytes(j: &serde_json::Value) -> Vec<u8> {
722 let s = j.as_str().unwrap_or_else(|| {
723 panic!("__json_to_bytes: JSON value {j} is not a string (expected hex)")
724 });
725 data_encoding::HEXLOWER_PERMISSIVE
726 .decode(s.as_bytes())
727 .unwrap_or_else(|e| panic!("__json_to_bytes: cannot hex-decode {s:?}: {e}"))
728}
729
730#[crate::polydat_node(category = Conversions)]
731fn __json_to_vec_f32(j: &serde_json::Value) -> Vec<f32> {
732 let arr = j
733 .as_array()
734 .unwrap_or_else(|| panic!("__json_to_vec_f32: JSON value {j} is not an array"));
735 arr.iter()
736 .map(|x| {
737 x.as_f64()
738 .unwrap_or_else(|| panic!("__json_to_vec_f32: element {x} is not a number"))
739 as f32
740 })
741 .collect()
742}
743
744#[crate::polydat_node(category = Conversions)]
745fn __json_to_vec_i32(j: &serde_json::Value) -> Vec<i32> {
746 let arr = j
747 .as_array()
748 .unwrap_or_else(|| panic!("__json_to_vec_i32: JSON value {j} is not an array"));
749 arr.iter()
750 .map(|x| {
751 let n = x
752 .as_i64()
753 .unwrap_or_else(|| panic!("__json_to_vec_i32: element {x} is not an integer"));
754 if !(i32::MIN as i64..=i32::MAX as i64).contains(&n) {
755 panic!(
756 "__json_to_vec_i32: element {n} out of i32 range [{}, {}]",
757 i32::MIN,
758 i32::MAX
759 );
760 }
761 n as i32
762 })
763 .collect()
764}
765
766#[crate::polydat_node(category = Conversions)]
778fn __vec_f32_to_str(elems: &[f32]) -> String {
779 let arr: Vec<serde_json::Value> = elems
780 .iter()
781 .map(|&f| {
782 serde_json::Value::Number(
783 serde_json::Number::from_f64(f as f64)
784 .unwrap_or_else(|| panic!("__vec_f32_to_str: non-finite element {f}")),
785 )
786 })
787 .collect();
788 serde_json::Value::Array(arr).to_string()
789}
790
791#[crate::polydat_node(category = Conversions)]
792fn __vec_i32_to_str(elems: &[i32]) -> String {
793 let arr: Vec<serde_json::Value> = elems
794 .iter()
795 .map(|&n| serde_json::Value::Number(serde_json::Number::from(n)))
796 .collect();
797 serde_json::Value::Array(arr).to_string()
798}
799
800#[crate::polydat_node(category = Conversions)]
801fn __vec_f32_to_bytes(elems: &[f32]) -> Vec<u8> {
802 let mut buf = Vec::with_capacity(elems.len() * 4);
803 for &f in elems {
804 buf.extend_from_slice(&f.to_le_bytes());
805 }
806 buf
807}
808
809#[crate::polydat_node(category = Conversions)]
810fn __vec_i32_to_bytes(elems: &[i32]) -> Vec<u8> {
811 let mut buf = Vec::with_capacity(elems.len() * 4);
812 for &n in elems {
813 buf.extend_from_slice(&n.to_le_bytes());
814 }
815 buf
816}
817
818#[crate::polydat_node(category = Conversions)]
819fn __vec_f32_to_json(elems: &[f32]) -> Arc<serde_json::Value> {
820 let arr: Vec<serde_json::Value> = elems
821 .iter()
822 .map(|&f| {
823 serde_json::Value::Number(
824 serde_json::Number::from_f64(f as f64)
825 .unwrap_or_else(|| panic!("__vec_f32_to_json: non-finite element {f}")),
826 )
827 })
828 .collect();
829 Arc::new(serde_json::Value::Array(arr))
830}
831
832#[crate::polydat_node(category = Conversions)]
833fn __vec_i32_to_json(elems: &[i32]) -> Arc<serde_json::Value> {
834 let arr: Vec<serde_json::Value> = elems
835 .iter()
836 .map(|&n| serde_json::Value::Number(serde_json::Number::from(n)))
837 .collect();
838 Arc::new(serde_json::Value::Array(arr))
839}
840
841#[crate::polydat_node(category = Conversions)]
842fn __vec_i32_to_vec_f32(elems: &[i32]) -> Vec<f32> {
843 elems.iter().map(|&n| n as f32).collect()
844}
845
846#[crate::polydat_node(category = Conversions)]
847fn __vec_f32_to_vec_i32(elems: &[f32]) -> Vec<i32> {
848 elems
849 .iter()
850 .map(|&f| {
851 if !f.is_finite() {
852 panic!("__vec_f32_to_vec_i32: non-finite element {f} cannot be represented as i32");
853 }
854 let rounded = f.round();
855 if rounded < i32::MIN as f32 || rounded > i32::MAX as f32 {
856 panic!(
857 "__vec_f32_to_vec_i32: element {f} out of i32 range [{}, {}]",
858 i32::MIN,
859 i32::MAX
860 );
861 }
862 rounded as i32
863 })
864 .collect()
865}
866
867#[cfg(test)]
872mod tests {
873 use super::*;
874 use crate::ast::{PolydatNode, SliceArc, Value};
875
876 fn check<N: PolydatNode>(node: &N, input: Value, expected: Value) {
877 let mut out = [Value::None];
878 node.eval(&[input], &mut out);
879 assert_eq!(
880 out[0],
881 expected,
882 "{} produced wrong output",
883 node.meta().name
884 );
885 }
886
887 fn check_panics<N: PolydatNode>(node: &N, input: Value, msg_substring: &str) {
888 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
889 let mut out = [Value::None];
890 node.eval(&[input], &mut out);
891 }));
892 match result {
893 Ok(_) => panic!("{} did not panic as expected", node.meta().name),
894 Err(payload) => {
895 let s = payload
896 .downcast_ref::<String>()
897 .cloned()
898 .or_else(|| payload.downcast_ref::<&'static str>().map(|s| (*s).into()))
899 .unwrap_or_default();
900 assert!(
901 s.contains(msg_substring),
902 "{} panicked but message didn't contain {msg_substring:?}: {s}",
903 node.meta().name
904 );
905 }
906 }
907 }
908
909 fn f32_value(f: f32) -> Value {
914 Value::U64(f.to_bits() as u64)
915 }
916
917 #[test]
922 fn numeric_narrowings_happy_path() {
923 check(&U64ToU32::new(), Value::U64(42), Value::U64(42));
924 check(&U64ToI64::new(), Value::U64(100), Value::I64(100));
925 check(&U64ToI32::new(), Value::U64(100), Value::I64(100));
926 check(&U64ToF32::new(), Value::U64(7), f32_value(7.0));
927 check(&U32ToI32::new(), Value::U64(50), Value::I64(50));
928 check(&U32ToF32::new(), Value::U64(3), f32_value(3.0));
929 check(&I64ToU64::new(), Value::I64(42), Value::U64(42));
930 check(&I64ToU32::new(), Value::I64(42), Value::U64(42));
931 check(&I64ToI32::new(), Value::I64(-100), Value::I64(-100));
932 check(&I32ToU64::new(), Value::I64(7), Value::U64(7));
933 check(&I32ToU32::new(), Value::I64(7), Value::U64(7));
934 check(&F64ToF32::new(), Value::F64(1.5), f32_value(1.5));
935 check(&F64ToU32::new(), Value::F64(42.7), Value::U64(42));
936 check(&F64ToI64::new(), Value::F64(-5.9), Value::I64(-5));
937 check(&F64ToI32::new(), Value::F64(-5.9), Value::I64(-5));
938 }
939
940 #[test]
941 fn numeric_narrowing_range_panics() {
942 check_panics(
943 &U64ToU32::new(),
944 Value::U64(u32::MAX as u64 + 1),
945 "exceeds u32::MAX",
946 );
947 check_panics(&U64ToI64::new(), Value::U64(u64::MAX), "exceeds i64::MAX");
948 check_panics(&I64ToU64::new(), Value::I64(-1), "negative");
949 check_panics(&I64ToI32::new(), Value::I64(i64::MAX), "out of i32 range");
950 check_panics(&F64ToU64Checked::new(), Value::F64(f64::NAN), "non-finite");
951 check_panics(
952 &F64ToU64Checked::new(),
953 Value::F64(-1.0),
954 "out of u64 range",
955 );
956 check_panics(&F64ToI32::new(), Value::F64(f64::INFINITY), "non-finite");
957 }
958
959 #[test]
964 fn bool_to_numerics_round_trip() {
965 check(&BoolToU32::new(), Value::Bool(true), Value::U64(1));
966 check(&BoolToI64::new(), Value::Bool(false), Value::I64(0));
967 check(&BoolToI32::new(), Value::Bool(true), Value::I64(1));
968 check(&BoolToF64::new(), Value::Bool(true), Value::F64(1.0));
969 check(&BoolToF32::new(), Value::Bool(false), f32_value(0.0));
970 check(&U32ToBool::new(), Value::U64(7), Value::Bool(true));
971 check(&U32ToBool::new(), Value::U64(0), Value::Bool(false));
972 check(&I64ToBool::new(), Value::I64(-1), Value::Bool(true));
973 check(&I32ToBool::new(), Value::I64(0), Value::Bool(false));
974 check(&F64ToBool::new(), Value::F64(0.1), Value::Bool(true));
975 check(&F64ToBool::new(), Value::F64(0.0), Value::Bool(false));
976 check(&F64ToBool::new(), Value::F64(f64::NAN), Value::Bool(false));
977 check(&F32ToBool::new(), f32_value(2.5), Value::Bool(true));
978 }
979
980 #[test]
985 fn str_to_narrow_numerics() {
986 check(&StrToU32::new(), Value::Str("42".into()), Value::U64(42));
987 check(
988 &StrToI64::new(),
989 Value::Str("-100".into()),
990 Value::I64(-100),
991 );
992 check(&StrToI32::new(), Value::Str("-7".into()), Value::I64(-7));
993 check(&StrToF32::new(), Value::Str("1.5".into()), f32_value(1.5));
994 check_panics(
995 &StrToU32::new(),
996 Value::Str("4294967296".into()),
997 "cannot parse",
998 );
999 check_panics(&StrToI32::new(), Value::Str("abc".into()), "cannot parse");
1000 }
1001
1002 #[test]
1003 fn str_to_bytes_hex_roundtrip() {
1004 check(
1005 &StrToBytes::new(),
1006 Value::Str("0a0b0c".into()),
1007 Value::Bytes(Arc::from(&[10u8, 11, 12][..])),
1008 );
1009 check_panics(
1010 &StrToBytes::new(),
1011 Value::Str("not hex!".into()),
1012 "hex-decode",
1013 );
1014 }
1015
1016 #[test]
1017 fn str_to_json_parses_or_wraps_error() {
1018 let node = StrToJson::new();
1020 let mut out = [Value::None];
1021 node.eval(&[Value::Str("[1, 2, 3]".into())], &mut out);
1022 match &out[0] {
1023 Value::Json(j) => {
1024 assert!(j.is_array());
1025 assert_eq!(j.as_array().unwrap().len(), 3);
1026 }
1027 other => panic!("expected Json::Array, got {other:?}"),
1028 }
1029 let mut out = [Value::None];
1031 node.eval(&[Value::Str("{bad json".into())], &mut out);
1032 match &out[0] {
1033 Value::Json(j) => {
1034 let obj = j.as_object().expect("error wrap is object");
1035 assert_eq!(
1036 obj.get("error").and_then(|v| v.as_str()),
1037 Some("invalid JSON")
1038 );
1039 assert_eq!(obj.get("raw").and_then(|v| v.as_str()), Some("{bad json"));
1040 assert!(obj.get("message").and_then(|v| v.as_str()).is_some());
1041 }
1042 other => panic!("expected Json error wrap, got {other:?}"),
1043 }
1044 }
1045
1046 #[test]
1047 fn str_to_vec_parses_arrays() {
1048 let mut out = [Value::None];
1049 StrToVecF32::new().eval(&[Value::Str("[1.0, 2.5, -3.0]".into())], &mut out);
1050 match &out[0] {
1051 Value::VecF32(arr) => assert_eq!(arr.as_ref(), &[1.0_f32, 2.5, -3.0]),
1052 other => panic!("expected VecF32, got {other:?}"),
1053 }
1054 let mut out = [Value::None];
1055 StrToVecI32::new().eval(&[Value::Str("[1, 2, -3]".into())], &mut out);
1056 match &out[0] {
1057 Value::VecI32(arr) => assert_eq!(arr.as_ref(), &[1_i32, 2, -3]),
1058 other => panic!("expected VecI32, got {other:?}"),
1059 }
1060 }
1061
1062 #[test]
1067 fn numeric_bytes_le_roundtrip() {
1068 let mut out = [Value::None];
1070 U64ToBytes::new().eval(&[Value::U64(0x0102030405060708)], &mut out);
1071 match &out[0] {
1072 Value::Bytes(b) => assert_eq!(b.as_ref(), &[8u8, 7, 6, 5, 4, 3, 2, 1]),
1073 other => panic!("expected Bytes, got {other:?}"),
1074 }
1075 let mut out = [Value::None];
1076 BytesToU64::new().eval(
1077 &[Value::Bytes(Arc::from(&[8u8, 7, 6, 5, 4, 3, 2, 1][..]))],
1078 &mut out,
1079 );
1080 assert_eq!(out[0], Value::U64(0x0102030405060708));
1081
1082 let mut out = [Value::None];
1084 U32ToBytes::new().eval(&[Value::U64(0x01020304)], &mut out);
1085 match &out[0] {
1086 Value::Bytes(b) => assert_eq!(b.as_ref(), &[4u8, 3, 2, 1]),
1087 other => panic!("expected Bytes, got {other:?}"),
1088 }
1089
1090 let mut out_b = [Value::None];
1092 F64ToBytes::new().eval(&[Value::F64(3.14)], &mut out_b);
1093 let bytes = match &out_b[0] {
1094 Value::Bytes(b) => b.clone(),
1095 _ => panic!(),
1096 };
1097 let mut out_f = [Value::None];
1098 BytesToF64::new().eval(&[Value::Bytes(bytes)], &mut out_f);
1099 assert_eq!(out_f[0], Value::F64(3.14));
1100 }
1101
1102 #[test]
1103 fn bytes_length_panics() {
1104 check_panics(
1105 &BytesToU64::new(),
1106 Value::Bytes(Arc::from(&[1u8, 2, 3][..])),
1107 "expected exactly 8 bytes",
1108 );
1109 check_panics(
1110 &BytesToU32::new(),
1111 Value::Bytes(Arc::from(&[1u8, 2, 3, 4, 5][..])),
1112 "expected exactly 4 bytes",
1113 );
1114 check_panics(
1115 &BytesToBool::new(),
1116 Value::Bytes(Arc::from(&[][..])),
1117 "expected exactly 1 byte",
1118 );
1119 }
1120
1121 #[test]
1122 fn bytes_str_lowercase_hex() {
1123 let mut out = [Value::None];
1124 BytesToStr::new().eval(
1125 &[Value::Bytes(Arc::from(&[0xDE_u8, 0xAD, 0xBE, 0xEF][..]))],
1126 &mut out,
1127 );
1128 match &out[0] {
1129 Value::Str(s) => assert_eq!(&**s, "deadbeef"),
1130 other => panic!("expected Str, got {other:?}"),
1131 }
1132 }
1133
1134 #[test]
1135 fn bytes_vec_roundtrip() {
1136 let mut out_b = [Value::None];
1138 VecF32ToBytes::new().eval(
1139 &[Value::VecF32(SliceArc::from_vec(vec![1.0_f32, 2.0, 3.0]))],
1140 &mut out_b,
1141 );
1142 let bytes = match &out_b[0] {
1143 Value::Bytes(b) => b.clone(),
1144 _ => panic!(),
1145 };
1146 let mut out_v = [Value::None];
1147 BytesToVecF32::new().eval(&[Value::Bytes(bytes)], &mut out_v);
1148 match &out_v[0] {
1149 Value::VecF32(arr) => assert_eq!(arr.as_ref(), &[1.0_f32, 2.0, 3.0]),
1150 other => panic!("expected VecF32, got {other:?}"),
1151 }
1152 check_panics(
1154 &BytesToVecF32::new(),
1155 Value::Bytes(Arc::from(&[1u8, 2, 3][..])),
1156 "not a multiple of 4",
1157 );
1158 }
1159
1160 #[test]
1165 fn json_scalar_roundtrip() {
1166 let mut out = [Value::None];
1167 U64ToJson::new().eval(&[Value::U64(42)], &mut out);
1168 let j = match &out[0] {
1169 Value::Json(j) => j.clone(),
1170 _ => panic!(),
1171 };
1172 let mut out_back = [Value::None];
1173 JsonToU64::new().eval(&[Value::Json(j)], &mut out_back);
1174 assert_eq!(out_back[0], Value::U64(42));
1175
1176 let mut out = [Value::None];
1177 BoolToJson::new().eval(&[Value::Bool(true)], &mut out);
1178 assert_eq!(out[0], Value::Json(Arc::new(serde_json::Value::Bool(true))));
1179 }
1180
1181 #[test]
1182 fn json_shape_panics() {
1183 check_panics(
1184 &JsonToU64::new(),
1185 Value::Json(Arc::new(serde_json::Value::String("abc".into()))),
1186 "is not a u64",
1187 );
1188 check_panics(
1189 &JsonToBool::new(),
1190 Value::Json(Arc::new(serde_json::Value::from(0))),
1191 "is not a bool",
1192 );
1193 check_panics(
1194 &JsonToVecF32::new(),
1195 Value::Json(Arc::new(serde_json::Value::Bool(false))),
1196 "is not an array",
1197 );
1198 }
1199
1200 #[test]
1201 fn json_bytes_via_hex() {
1202 let mut out_j = [Value::None];
1203 BytesToJson::new().eval(&[Value::Bytes(Arc::from(&[0xDE_u8, 0xAD][..]))], &mut out_j);
1204 let j = match &out_j[0] {
1205 Value::Json(j) => j.clone(),
1206 _ => panic!(),
1207 };
1208 assert_eq!(j.as_str(), Some("dead"));
1209 let mut out_b = [Value::None];
1210 JsonToBytes::new().eval(&[Value::Json(j)], &mut out_b);
1211 match &out_b[0] {
1212 Value::Bytes(b) => assert_eq!(b.as_ref(), &[0xDE_u8, 0xAD]),
1213 other => panic!("expected Bytes, got {other:?}"),
1214 }
1215 }
1216
1217 #[test]
1218 fn float_to_json_non_finite_panics() {
1219 check_panics(&F64ToJson::new(), Value::F64(f64::NAN), "non-finite");
1220 }
1221
1222 #[test]
1227 fn vec_cast_lossless_and_lossy() {
1228 let mut out = [Value::None];
1230 VecI32ToVecF32::new().eval(
1231 &[Value::VecI32(SliceArc::from_vec(vec![1_i32, -2, 3]))],
1232 &mut out,
1233 );
1234 match &out[0] {
1235 Value::VecF32(arr) => assert_eq!(arr.as_ref(), &[1.0_f32, -2.0, 3.0]),
1236 other => panic!("expected VecF32, got {other:?}"),
1237 }
1238
1239 let mut out = [Value::None];
1241 VecF32ToVecI32::new().eval(
1242 &[Value::VecF32(SliceArc::from_vec(vec![1.4_f32, 2.7, -3.5]))],
1243 &mut out,
1244 );
1245 match &out[0] {
1246 Value::VecI32(arr) => assert_eq!(arr.as_ref(), &[1_i32, 3, -4]),
1247 other => panic!("expected VecI32, got {other:?}"),
1248 }
1249 check_panics(
1250 &VecF32ToVecI32::new(),
1251 Value::VecF32(SliceArc::from_vec(vec![f32::INFINITY])),
1252 "non-finite",
1253 );
1254 }
1255
1256 #[test]
1257 fn vec_str_json_serialization() {
1258 let mut out = [Value::None];
1259 VecI32ToStr::new().eval(
1260 &[Value::VecI32(SliceArc::from_vec(vec![1_i32, 2, 3]))],
1261 &mut out,
1262 );
1263 match &out[0] {
1264 Value::Str(s) => assert_eq!(&**s, "[1,2,3]"),
1265 other => panic!("expected Str, got {other:?}"),
1266 }
1267
1268 let mut out = [Value::None];
1269 VecF32ToJson::new().eval(
1270 &[Value::VecF32(SliceArc::from_vec(vec![1.5_f32, 2.0]))],
1271 &mut out,
1272 );
1273 match &out[0] {
1274 Value::Json(j) => {
1275 assert!(j.is_array());
1276 let arr = j.as_array().unwrap();
1277 assert_eq!(arr[0].as_f64().unwrap() as f32, 1.5_f32);
1278 assert_eq!(arr[1].as_f64().unwrap() as f32, 2.0_f32);
1279 }
1280 other => panic!("expected Json, got {other:?}"),
1281 }
1282 }
1283}