stellar_xdr/curr/
scval_conversions.rs

1use super::{
2    Int128Parts, ScBytes, ScError, ScMap, ScMapEntry, ScSymbol, ScVal, ScVec, UInt128Parts,
3};
4
5#[cfg(all(not(feature = "std"), feature = "alloc"))]
6extern crate alloc;
7#[cfg(all(not(feature = "std"), feature = "alloc"))]
8use alloc::{string::String, vec, vec::Vec};
9
10// TODO: Use the Error type for conversions in this file.
11
12impl From<ScError> for ScVal {
13    fn from(v: ScError) -> Self {
14        ScVal::Error(v)
15    }
16}
17
18impl TryFrom<ScVal> for ScError {
19    type Error = ();
20    fn try_from(v: ScVal) -> Result<Self, Self::Error> {
21        if let ScVal::Error(s) = v {
22            Ok(s)
23        } else {
24            Err(())
25        }
26    }
27}
28
29impl From<i32> for ScVal {
30    fn from(v: i32) -> ScVal {
31        ScVal::I32(v)
32    }
33}
34
35impl From<&i32> for ScVal {
36    fn from(v: &i32) -> ScVal {
37        ScVal::I32(*v)
38    }
39}
40
41impl TryFrom<ScVal> for i32 {
42    type Error = ();
43    fn try_from(v: ScVal) -> Result<Self, Self::Error> {
44        if let ScVal::I32(i) = v {
45            Ok(i)
46        } else {
47            Err(())
48        }
49    }
50}
51
52impl From<u32> for ScVal {
53    fn from(v: u32) -> ScVal {
54        ScVal::U32(v)
55    }
56}
57
58impl From<&u32> for ScVal {
59    fn from(v: &u32) -> ScVal {
60        ScVal::U32(*v)
61    }
62}
63
64impl TryFrom<ScVal> for u32 {
65    type Error = ();
66    fn try_from(v: ScVal) -> Result<Self, Self::Error> {
67        if let ScVal::U32(i) = v {
68            Ok(i)
69        } else {
70            Err(())
71        }
72    }
73}
74
75impl From<i64> for ScVal {
76    fn from(v: i64) -> ScVal {
77        ScVal::I64(v)
78    }
79}
80
81impl From<&i64> for ScVal {
82    fn from(v: &i64) -> ScVal {
83        <_ as Into<ScVal>>::into(*v)
84    }
85}
86
87impl TryFrom<ScVal> for i64 {
88    type Error = ();
89    fn try_from(v: ScVal) -> Result<Self, Self::Error> {
90        if let ScVal::I64(i) = v {
91            Ok(i)
92        } else {
93            Err(())
94        }
95    }
96}
97
98impl From<()> for ScVal {
99    fn from((): ()) -> Self {
100        ScVal::Void
101    }
102}
103
104impl From<&()> for ScVal {
105    fn from((): &()) -> Self {
106        ScVal::Void
107    }
108}
109
110impl TryFrom<ScVal> for () {
111    type Error = ();
112    fn try_from(v: ScVal) -> Result<Self, Self::Error> {
113        if let ScVal::Void = v {
114            Ok(())
115        } else {
116            Err(())
117        }
118    }
119}
120
121impl From<bool> for ScVal {
122    fn from(v: bool) -> Self {
123        ScVal::Bool(v)
124    }
125}
126
127impl From<&bool> for ScVal {
128    fn from(v: &bool) -> Self {
129        <_ as Into<ScVal>>::into(*v)
130    }
131}
132
133impl TryFrom<ScVal> for bool {
134    type Error = ();
135    fn try_from(v: ScVal) -> Result<Self, Self::Error> {
136        if let ScVal::Bool(b) = v {
137            Ok(b)
138        } else {
139            Err(())
140        }
141    }
142}
143
144impl From<u64> for ScVal {
145    fn from(v: u64) -> Self {
146        ScVal::U64(v)
147    }
148}
149
150impl From<&u64> for ScVal {
151    fn from(v: &u64) -> Self {
152        ScVal::U64(*v)
153    }
154}
155
156impl TryFrom<ScVal> for u64 {
157    type Error = ();
158    fn try_from(v: ScVal) -> Result<Self, Self::Error> {
159        if let ScVal::U64(i) = v {
160            Ok(i)
161        } else {
162            Err(())
163        }
164    }
165}
166
167pub mod int128_helpers {
168    #[must_use]
169    #[inline(always)]
170    #[allow(clippy::inline_always, clippy::cast_possible_truncation)]
171    pub fn u128_hi(u: u128) -> u64 {
172        (u >> 64) as u64
173    }
174
175    #[must_use]
176    #[inline(always)]
177    #[allow(clippy::inline_always, clippy::cast_possible_truncation)]
178    pub fn u128_lo(u: u128) -> u64 {
179        u as u64
180    }
181
182    #[must_use]
183    #[inline(always)]
184    #[allow(clippy::inline_always)]
185    pub fn u128_from_pieces(hi: u64, lo: u64) -> u128 {
186        (u128::from(hi) << 64) | u128::from(lo)
187    }
188
189    #[must_use]
190    #[inline(always)]
191    #[allow(clippy::inline_always, clippy::cast_possible_truncation)]
192    pub fn i128_hi(i: i128) -> i64 {
193        (i >> 64) as i64
194    }
195
196    #[must_use]
197    #[inline(always)]
198    #[allow(
199        clippy::inline_always,
200        clippy::cast_possible_truncation,
201        clippy::cast_sign_loss
202    )]
203    pub fn i128_lo(i: i128) -> u64 {
204        i as u64
205    }
206
207    #[must_use]
208    #[inline(always)]
209    #[allow(
210        clippy::inline_always,
211        clippy::cast_sign_loss,
212        clippy::cast_possible_wrap
213    )]
214    pub fn i128_from_pieces(hi: i64, lo: u64) -> i128 {
215        (u128::from(hi as u64) << 64 | u128::from(lo)) as i128
216    }
217}
218
219#[allow(clippy::wildcard_imports)]
220use int128_helpers::*;
221
222impl From<u128> for ScVal {
223    fn from(v: u128) -> Self {
224        ScVal::U128(UInt128Parts {
225            hi: u128_hi(v),
226            lo: u128_lo(v),
227        })
228    }
229}
230
231impl From<&u128> for ScVal {
232    fn from(v: &u128) -> Self {
233        <ScVal as From<u128>>::from(*v)
234    }
235}
236
237impl From<&UInt128Parts> for u128 {
238    fn from(v: &UInt128Parts) -> Self {
239        u128_from_pieces(v.hi, v.lo)
240    }
241}
242
243impl TryFrom<ScVal> for u128 {
244    type Error = ();
245    fn try_from(v: ScVal) -> Result<Self, Self::Error> {
246        if let ScVal::U128(i) = v {
247            Ok((&i).into())
248        } else {
249            Err(())
250        }
251    }
252}
253
254impl From<i128> for ScVal {
255    fn from(v: i128) -> Self {
256        ScVal::I128(Int128Parts {
257            hi: i128_hi(v),
258            lo: i128_lo(v),
259        })
260    }
261}
262
263impl From<&i128> for ScVal {
264    fn from(v: &i128) -> Self {
265        <ScVal as From<i128>>::from(*v)
266    }
267}
268
269impl From<&Int128Parts> for i128 {
270    fn from(v: &Int128Parts) -> Self {
271        i128_from_pieces(v.hi, v.lo)
272    }
273}
274
275impl TryFrom<ScVal> for i128 {
276    type Error = ();
277    fn try_from(v: ScVal) -> Result<Self, Self::Error> {
278        if let ScVal::I128(i) = v {
279            Ok((&i).into())
280        } else {
281            Err(())
282        }
283    }
284}
285
286impl From<ScSymbol> for ScVal {
287    fn from(v: ScSymbol) -> Self {
288        ScVal::Symbol(v)
289    }
290}
291
292impl TryFrom<ScVal> for ScSymbol {
293    type Error = ();
294    fn try_from(v: ScVal) -> Result<Self, Self::Error> {
295        if let ScVal::Symbol(s) = v {
296            Ok(s)
297        } else {
298            Err(())
299        }
300    }
301}
302
303#[cfg(feature = "alloc")]
304impl TryFrom<String> for ScSymbol {
305    type Error = ();
306    fn try_from(v: String) -> Result<Self, Self::Error> {
307        Ok(ScSymbol(v.try_into().map_err(|_| ())?))
308    }
309}
310
311#[cfg(feature = "alloc")]
312impl TryFrom<&String> for ScSymbol {
313    type Error = ();
314    fn try_from(v: &String) -> Result<Self, Self::Error> {
315        Ok(ScSymbol(v.try_into().map_err(|_| ())?))
316    }
317}
318
319#[cfg(feature = "alloc")]
320impl TryFrom<&str> for ScSymbol {
321    type Error = ();
322    fn try_from(v: &str) -> Result<Self, Self::Error> {
323        Ok(ScSymbol(v.try_into().map_err(|_| ())?))
324    }
325}
326
327#[cfg(not(feature = "alloc"))]
328impl TryFrom<&'static str> for ScSymbol {
329    type Error = ();
330    fn try_from(v: &'static str) -> Result<Self, Self::Error> {
331        Ok(ScSymbol(v.try_into().map_err(|_| ())?))
332    }
333}
334
335#[cfg(feature = "alloc")]
336impl TryFrom<Vec<u8>> for ScVal {
337    type Error = ();
338    fn try_from(v: Vec<u8>) -> Result<Self, ()> {
339        Ok(ScVal::Bytes(ScBytes(v.try_into().map_err(|_| ())?)))
340    }
341}
342
343#[cfg(feature = "alloc")]
344impl TryFrom<&Vec<u8>> for ScVal {
345    type Error = ();
346    fn try_from(v: &Vec<u8>) -> Result<Self, ()> {
347        Ok(ScVal::Bytes(ScBytes(v.try_into().map_err(|_| ())?)))
348    }
349}
350
351#[cfg(feature = "alloc")]
352impl TryFrom<&[u8]> for ScVal {
353    type Error = ();
354    fn try_from(v: &[u8]) -> Result<Self, ()> {
355        Ok(ScVal::Bytes(ScBytes(v.try_into().map_err(|_| ())?)))
356    }
357}
358
359#[cfg(feature = "alloc")]
360impl<const N: usize> TryFrom<[u8; N]> for ScVal {
361    type Error = ();
362    fn try_from(v: [u8; N]) -> Result<Self, ()> {
363        Ok(ScVal::Bytes(ScBytes(v.try_into().map_err(|_| ())?)))
364    }
365}
366
367#[cfg(feature = "alloc")]
368impl<const N: usize> TryFrom<&[u8; N]> for ScVal {
369    type Error = ();
370    fn try_from(v: &[u8; N]) -> Result<Self, ()> {
371        Ok(ScVal::Bytes(ScBytes(v.try_into().map_err(|_| ())?)))
372    }
373}
374
375#[cfg(not(feature = "alloc"))]
376impl TryFrom<&'static [u8]> for ScVal {
377    type Error = ();
378    fn try_from(v: &'static [u8]) -> Result<Self, ()> {
379        Ok(ScVal::Bytes(ScBytes(v.try_into().map_err(|_| ())?)))
380    }
381}
382
383#[cfg(feature = "alloc")]
384impl TryFrom<ScVal> for Vec<u8> {
385    type Error = ();
386    fn try_from(v: ScVal) -> Result<Self, Self::Error> {
387        if let ScVal::Bytes(ScBytes(b)) = v {
388            Ok(b.into())
389        } else {
390            Err(())
391        }
392    }
393}
394
395#[cfg(feature = "alloc")]
396impl TryFrom<&ScVal> for Vec<u8> {
397    type Error = ();
398    fn try_from(v: &ScVal) -> Result<Self, Self::Error> {
399        if let ScVal::Bytes(ScBytes(b)) = v {
400            Ok(b.into())
401        } else {
402            Err(())
403        }
404    }
405}
406
407impl From<ScVec> for ScVal {
408    fn from(v: ScVec) -> Self {
409        ScVal::Vec(Some(v))
410    }
411}
412
413#[cfg(feature = "alloc")]
414impl<T: TryInto<ScVal>> TryFrom<Vec<T>> for ScVal {
415    type Error = ();
416    fn try_from(v: Vec<T>) -> Result<Self, ()> {
417        Ok(ScVal::Vec(Some(
418            v.into_iter()
419                .map(|t| <_ as TryInto<ScVal>>::try_into(t))
420                .collect::<Result<Vec<_>, _>>() // TODO: Impl conversion from Iterator to VecM in xdrgen generated code.
421                .map_err(|_| ())?
422                .try_into()
423                .map_err(|_| ())?,
424        )))
425    }
426}
427
428#[cfg(feature = "alloc")]
429impl<T: TryInto<ScVal> + Clone> TryFrom<&Vec<T>> for ScVal {
430    type Error = ();
431    fn try_from(v: &Vec<T>) -> Result<Self, ()> {
432        Ok(ScVal::Vec(Some(
433            v.iter()
434                .map(|t| <_ as TryInto<ScVal>>::try_into(t.clone()))
435                .collect::<Result<Vec<_>, _>>() // TODO: Impl conversion from Iterator to VecM in xdrgen generated code.
436                .map_err(|_| ())?
437                .try_into()
438                .map_err(|_| ())?,
439        )))
440    }
441}
442
443#[cfg(feature = "alloc")]
444impl<T: TryInto<ScVal> + Clone> TryFrom<&[T]> for ScVal {
445    type Error = ();
446    fn try_from(v: &[T]) -> Result<Self, ()> {
447        Ok(ScVal::Vec(Some(
448            v.iter()
449                .map(|t| <_ as TryInto<ScVal>>::try_into(t.clone()))
450                .collect::<Result<Vec<_>, _>>() // TODO: Impl conversion from Iterator to VecM in xdrgen generated code.
451                .map_err(|_| ())?
452                .try_into()
453                .map_err(|_| ())?,
454        )))
455    }
456}
457
458#[cfg(feature = "alloc")]
459impl<T: TryFrom<ScVal> + Clone> TryFrom<ScVal> for Vec<T> {
460    type Error = ();
461    fn try_from(v: ScVal) -> Result<Self, Self::Error> {
462        if let ScVal::Vec(Some(v)) = v {
463            v.iter()
464                .map(|t| T::try_from(t.clone()).map_err(|_| ()))
465                .collect::<Result<Vec<T>, _>>()
466        } else {
467            Err(())
468        }
469    }
470}
471
472impl From<ScMap> for ScVal {
473    fn from(v: ScMap) -> Self {
474        ScVal::Map(Some(v))
475    }
476}
477
478impl TryFrom<ScVal> for ScMap {
479    type Error = ();
480    fn try_from(v: ScVal) -> Result<Self, Self::Error> {
481        if let ScVal::Map(Some(m)) = v {
482            Ok(m)
483        } else {
484            Err(())
485        }
486    }
487}
488
489impl<K, V> TryFrom<(K, V)> for ScMapEntry
490where
491    K: TryInto<ScVal>,
492    V: TryInto<ScVal>,
493{
494    type Error = ();
495
496    fn try_from(v: (K, V)) -> Result<Self, Self::Error> {
497        Ok(ScMapEntry {
498            key: v.0.try_into().map_err(|_| ())?,
499            val: v.1.try_into().map_err(|_| ())?,
500        })
501    }
502}
503
504// TODO: Add conversions from std::collections::HashMap, im_rcOrdMap, and other
505// popular map types to ScMap.
506
507impl<T> From<Option<T>> for ScVal
508where
509    T: Into<ScVal>,
510{
511    fn from(v: Option<T>) -> Self {
512        match v {
513            Some(v) => v.into(),
514            None => ().into(),
515        }
516    }
517}
518
519impl<T> From<&Option<T>> for ScVal
520where
521    T: Into<ScVal> + Clone,
522{
523    fn from(v: &Option<T>) -> Self {
524        match v {
525            Some(v) => v.clone().into(),
526            None => ().into(),
527        }
528    }
529}
530
531macro_rules! impl_for_tuple {
532    ( $count:literal $($typ:ident $idx:tt)+ ) => {
533        #[cfg(feature = "alloc")]
534        impl<$($typ),*> TryFrom<($($typ,)*)> for ScVec
535        where
536            $($typ: TryInto<ScVal>),*
537        {
538            type Error = ();
539            fn try_from(v: ($($typ,)*)) -> Result<Self, Self::Error> {
540                let vec: Vec<ScVal> = vec![$(v.$idx.try_into().map_err(|_| ())?),+];
541                Ok(ScVec(vec.try_into()?))
542            }
543        }
544
545        #[cfg(feature = "alloc")]
546        impl<$($typ),*> TryFrom<&($($typ,)*)> for ScVec
547        where
548            $($typ: TryInto<ScVal> + Clone),*
549        {
550            type Error = ();
551            fn try_from(v: &($($typ,)*)) -> Result<Self, Self::Error> {
552                let vec: Vec<ScVal> = vec![$(v.$idx.clone().try_into().map_err(|_| ())?),+];
553                Ok(ScVec(vec.try_into()?))
554            }
555        }
556
557        #[cfg(feature = "alloc")]
558        impl<$($typ),*> TryFrom<($($typ,)*)> for ScVal
559        where
560            $($typ: TryInto<ScVal>),*
561        {
562            type Error = ();
563            fn try_from(v: ($($typ,)*)) -> Result<Self, ()> {
564                Ok(ScVal::Vec(Some(<_ as TryInto<ScVec>>::try_into(v)?)))
565            }
566        }
567
568        #[cfg(feature = "alloc")]
569        impl<$($typ),*> TryFrom<&($($typ,)*)> for ScVal
570        where
571            $($typ: TryInto<ScVal> + Clone),*
572        {
573            type Error = ();
574            fn try_from(v: &($($typ,)*)) -> Result<Self, ()> {
575                Ok(ScVal::Vec(Some(<_ as TryInto<ScVec>>::try_into(v)?)))
576            }
577        }
578
579        impl<$($typ),*> TryFrom<ScVec> for ($($typ,)*)
580        where
581            // TODO: Consider removing the Clone constraint by changing the
582            // try_from to use a reference.
583            $($typ: TryFrom<ScVal> + Clone),*
584        {
585            type Error = ();
586
587            fn try_from(vec: ScVec) -> Result<Self, Self::Error> {
588                if vec.len() != $count {
589                    return Err(());
590                }
591                Ok((
592                    $({
593                        let idx: usize = $idx;
594                        let val = vec[idx].clone();
595                        $typ::try_from(val).map_err(|_| ())?
596                    },)*
597                ))
598            }
599        }
600
601        impl<$($typ),*> TryFrom<ScVal> for ($($typ,)*)
602        where
603            $($typ: TryFrom<ScVal> + Clone),*
604        {
605            type Error = ();
606
607            fn try_from(obj: ScVal) -> Result<Self, Self::Error> {
608                if let ScVal::Vec(Some(vec)) = obj {
609                    <_ as TryFrom<ScVec>>::try_from(vec)
610                } else {
611                    Err(())
612                }
613            }
614        }
615    };
616}
617
618impl_for_tuple! {  1 T0 0 }
619impl_for_tuple! {  2 T0 0 T1 1 }
620impl_for_tuple! {  3 T0 0 T1 1 T2 2 }
621impl_for_tuple! {  4 T0 0 T1 1 T2 2 T3 3 }
622impl_for_tuple! {  5 T0 0 T1 1 T2 2 T3 3 T4 4 }
623impl_for_tuple! {  6 T0 0 T1 1 T2 2 T3 3 T4 4 T5 5 }
624impl_for_tuple! {  7 T0 0 T1 1 T2 2 T3 3 T4 4 T5 5 T6 6 }
625impl_for_tuple! {  8 T0 0 T1 1 T2 2 T3 3 T4 4 T5 5 T6 6 T7 7 }
626impl_for_tuple! {  9 T0 0 T1 1 T2 2 T3 3 T4 4 T5 5 T6 6 T7 7 T8 8 }
627impl_for_tuple! { 10 T0 0 T1 1 T2 2 T3 3 T4 4 T5 5 T6 6 T7 7 T8 8 T9 9 }
628impl_for_tuple! { 11 T0 0 T1 1 T2 2 T3 3 T4 4 T5 5 T6 6 T7 7 T8 8 T9 9 T10 10 }
629impl_for_tuple! { 12 T0 0 T1 1 T2 2 T3 3 T4 4 T5 5 T6 6 T7 7 T8 8 T9 9 T10 10 T11 11 }
630impl_for_tuple! { 13 T0 0 T1 1 T2 2 T3 3 T4 4 T5 5 T6 6 T7 7 T8 8 T9 9 T10 10 T11 11 T12 12 }
631
632#[cfg(test)]
633mod test {
634    use super::{int128_helpers, Int128Parts, ScVal, ScVec, UInt128Parts};
635
636    #[test]
637    fn i32_pos() {
638        let v = 5;
639        let val: ScVal = v.into();
640        assert_eq!(val, ScVal::I32(5));
641        let roundtrip: i32 = val.try_into().unwrap();
642        assert_eq!(v, roundtrip);
643    }
644
645    #[test]
646    fn i32_neg() {
647        let v = -5;
648        let val: ScVal = v.into();
649        assert_eq!(val, ScVal::I32(-5));
650        let roundtrip: i32 = val.try_into().unwrap();
651        assert_eq!(v, roundtrip);
652    }
653
654    #[test]
655    fn u32() {
656        use super::ScVal;
657
658        let v = 5u32;
659        let val: ScVal = v.into();
660        assert_eq!(val, ScVal::U32(5));
661        let roundtrip: u32 = val.try_into().unwrap();
662        assert_eq!(v, roundtrip);
663    }
664
665    #[test]
666    fn i64_pos() {
667        let v = 5i64;
668        let val: ScVal = v.into();
669        assert_eq!(val, ScVal::I64(5));
670        let roundtrip: i64 = val.try_into().unwrap();
671        assert_eq!(v, roundtrip);
672    }
673
674    #[test]
675    fn i64_neg() {
676        let v = -5i64;
677        let val: ScVal = v.into();
678        assert_eq!(val, ScVal::I64(-5));
679        let roundtrip: i64 = val.try_into().unwrap();
680        assert_eq!(v, roundtrip);
681    }
682
683    #[test]
684    fn u64() {
685        let v = 5u64;
686        let val: ScVal = v.into();
687        assert_eq!(val, ScVal::U64(5));
688        let roundtrip: u64 = val.try_into().unwrap();
689        assert_eq!(v, roundtrip);
690    }
691
692    #[test]
693    fn u128() {
694        let hi = 0x1234_5678_9abc_def0u64;
695        let lo = 0xfedc_ba98_7654_3210u64;
696        let u = int128_helpers::u128_from_pieces(hi, lo);
697        assert_eq!(u, 0x1234_5678_9abc_def0_fedc_ba98_7654_3210);
698        assert_eq!(int128_helpers::u128_hi(u), hi);
699        assert_eq!(int128_helpers::u128_lo(u), lo);
700
701        let val: ScVal = u.into();
702        assert_eq!(val, ScVal::U128(UInt128Parts { hi, lo }));
703        let roundtrip: u128 = val.try_into().unwrap();
704        assert_eq!(u, roundtrip);
705    }
706
707    #[test]
708    #[allow(clippy::cast_sign_loss, clippy::cast_possible_wrap)]
709    fn i128() {
710        let part1 = 0x00ab_cdef_9876_5432u64; // some positive int64
711        let part2 = 0xfedc_ba98_7654_3210u64; // some negative int64
712        let roundtrip = |hi: i64, lo: u64, ref_i128: i128| {
713            let i = int128_helpers::i128_from_pieces(hi, lo);
714            assert_eq!(i, ref_i128);
715            assert_eq!(int128_helpers::i128_hi(i), hi);
716            assert_eq!(int128_helpers::i128_lo(i), lo);
717
718            let val: ScVal = i.into();
719            assert_eq!(val, ScVal::I128(Int128Parts { hi, lo }));
720            let roundtrip: i128 = val.try_into().unwrap();
721            assert_eq!(i, roundtrip);
722        };
723        roundtrip(
724            part1 as i64,
725            part1,
726            0x00ab_cdef_9876_5432_00ab_cdef_9876_5432,
727        );
728        roundtrip(
729            part2 as i64,
730            part2,
731            0xfedc_ba98_7654_3210_fedc_ba98_7654_3210u128 as i128,
732        );
733        roundtrip(
734            part1 as i64,
735            part2,
736            0x00ab_cdef_9876_5432_fedc_ba98_7654_3210,
737        );
738        roundtrip(
739            part2 as i64,
740            part1,
741            0xfedc_ba98_7654_3210_00ab_cdef_9876_5432u128 as i128,
742        );
743    }
744
745    #[cfg(feature = "alloc")]
746    #[test]
747    fn binary() {
748        extern crate alloc;
749        use alloc::vec;
750
751        let v = [1, 2, 3, 4, 5];
752        let val: ScVal = v.try_into().unwrap();
753        assert_eq!(val, ScVal::Bytes(vec![1, 2, 3, 4, 5].try_into().unwrap()));
754
755        let v = &[1, 2, 3, 4, 5];
756        let val: ScVal = v.try_into().unwrap();
757        assert_eq!(val, ScVal::Bytes(vec![1, 2, 3, 4, 5].try_into().unwrap()));
758    }
759
760    #[cfg(feature = "alloc")]
761    #[test]
762    fn vec() {
763        extern crate alloc;
764        use alloc::vec;
765        use alloc::vec::Vec;
766
767        let v = vec![1, 2, 3, 4, 5];
768        let val: ScVal = v.clone().try_into().unwrap();
769        let roundtrip: Vec<i32> = val.try_into().unwrap();
770        assert_eq!(v, roundtrip);
771
772        let v = vec![vec![true], vec![false]];
773        let val: ScVal = v.clone().try_into().unwrap();
774        let roundtrip: Vec<Vec<bool>> = val.try_into().unwrap();
775        assert_eq!(v, roundtrip);
776    }
777
778    #[cfg(feature = "alloc")]
779    #[test]
780    fn tuple() {
781        extern crate alloc;
782        use alloc::vec;
783        use alloc::vec::Vec;
784        let v = (1i32, 2i64, vec![true, false]);
785        let val: ScVal = v.clone().try_into().unwrap();
786        let roundtrip: (i32, i64, Vec<bool>) = val.try_into().unwrap();
787        assert_eq!(v, roundtrip);
788    }
789
790    #[cfg(feature = "alloc")]
791    #[test]
792    fn tuple_refs() {
793        extern crate alloc;
794        use alloc::vec;
795        use alloc::vec::Vec;
796        let v = &(1i32, 2i64, vec![true, false]);
797        let val: ScVal = v.try_into().unwrap();
798        let roundtrip: (i32, i64, Vec<bool>) = val.try_into().unwrap();
799        assert_eq!(v, &roundtrip);
800    }
801
802    #[test]
803    fn option() {
804        let v: Option<i64> = Some(1);
805        let val: ScVal = v.into();
806        assert_eq!(val, ScVal::I64(1));
807
808        let v: Option<i64> = None;
809        let val: ScVal = v.into();
810        assert_eq!(val, ScVal::Void);
811    }
812
813    #[test]
814    fn scval_from() {
815        let _ = ScVal::from(ScVec::default());
816    }
817}