1#![allow(clippy::field_reassign_with_default)]
3
4use alloc::{
5 boxed::Box,
6 collections::{BTreeMap, BTreeSet, VecDeque},
7 string::String,
8 vec::Vec,
9};
10use core::mem;
11
12#[cfg(feature = "datasize")]
13use datasize::DataSize;
14use num_rational::Ratio;
15#[cfg(feature = "json-schema")]
16use schemars::JsonSchema;
17use serde::{Deserialize, Serialize};
18
19use crate::{
20 bytesrepr::{self, FromBytes, ToBytes},
21 Key, URef, U128, U256, U512,
22};
23
24pub(crate) const CL_TYPE_RECURSION_DEPTH: u8 = 50;
26
27const CL_TYPE_TAG_BOOL: u8 = 0;
28const CL_TYPE_TAG_I32: u8 = 1;
29const CL_TYPE_TAG_I64: u8 = 2;
30const CL_TYPE_TAG_U8: u8 = 3;
31const CL_TYPE_TAG_U32: u8 = 4;
32const CL_TYPE_TAG_U64: u8 = 5;
33const CL_TYPE_TAG_U128: u8 = 6;
34const CL_TYPE_TAG_U256: u8 = 7;
35const CL_TYPE_TAG_U512: u8 = 8;
36const CL_TYPE_TAG_UNIT: u8 = 9;
37const CL_TYPE_TAG_STRING: u8 = 10;
38const CL_TYPE_TAG_KEY: u8 = 11;
39const CL_TYPE_TAG_UREF: u8 = 12;
40const CL_TYPE_TAG_OPTION: u8 = 13;
41const CL_TYPE_TAG_LIST: u8 = 14;
42const CL_TYPE_TAG_BYTE_ARRAY: u8 = 15;
43const CL_TYPE_TAG_RESULT: u8 = 16;
44const CL_TYPE_TAG_MAP: u8 = 17;
45const CL_TYPE_TAG_TUPLE1: u8 = 18;
46const CL_TYPE_TAG_TUPLE2: u8 = 19;
47const CL_TYPE_TAG_TUPLE3: u8 = 20;
48const CL_TYPE_TAG_ANY: u8 = 21;
49const CL_TYPE_TAG_PUBLIC_KEY: u8 = 22;
50
51#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Serialize, Deserialize, Debug)]
55#[cfg_attr(feature = "datasize", derive(DataSize))]
56#[cfg_attr(feature = "json-schema", derive(JsonSchema))]
57#[serde(deny_unknown_fields)]
58pub enum CLType {
59 Bool,
61 I32,
63 I64,
65 U8,
67 U32,
69 U64,
71 U128,
73 U256,
75 U512,
77 Unit,
79 String,
81 Key,
83 URef,
85 PublicKey,
87 #[cfg_attr(feature = "datasize", data_size(skip))]
89 Option(Box<CLType>),
90 #[cfg_attr(feature = "datasize", data_size(skip))]
92 List(Box<CLType>),
93 ByteArray(u32),
95 #[allow(missing_docs)] #[cfg_attr(feature = "datasize", data_size(skip))]
98 Result { ok: Box<CLType>, err: Box<CLType> },
99 #[allow(missing_docs)] #[cfg_attr(feature = "datasize", data_size(skip))]
102 Map {
103 key: Box<CLType>,
104 value: Box<CLType>,
105 },
106 #[cfg_attr(feature = "datasize", data_size(skip))]
108 Tuple1([Box<CLType>; 1]),
109 #[cfg_attr(feature = "datasize", data_size(skip))]
111 Tuple2([Box<CLType>; 2]),
112 #[cfg_attr(feature = "datasize", data_size(skip))]
114 Tuple3([Box<CLType>; 3]),
115 Any,
117}
118
119impl CLType {
120 pub fn serialized_length(&self) -> usize {
122 mem::size_of::<u8>()
123 + match self {
124 CLType::Bool
125 | CLType::I32
126 | CLType::I64
127 | CLType::U8
128 | CLType::U32
129 | CLType::U64
130 | CLType::U128
131 | CLType::U256
132 | CLType::U512
133 | CLType::Unit
134 | CLType::String
135 | CLType::Key
136 | CLType::URef
137 | CLType::PublicKey
138 | CLType::Any => 0,
139 CLType::Option(cl_type) | CLType::List(cl_type) => cl_type.serialized_length(),
140 CLType::ByteArray(list_len) => list_len.serialized_length(),
141 CLType::Result { ok, err } => ok.serialized_length() + err.serialized_length(),
142 CLType::Map { key, value } => key.serialized_length() + value.serialized_length(),
143 CLType::Tuple1(cl_type_array) => serialized_length_of_cl_tuple_type(cl_type_array),
144 CLType::Tuple2(cl_type_array) => serialized_length_of_cl_tuple_type(cl_type_array),
145 CLType::Tuple3(cl_type_array) => serialized_length_of_cl_tuple_type(cl_type_array),
146 }
147 }
148
149 pub fn is_option(&self) -> bool {
151 matches!(self, Self::Option(..))
152 }
153}
154
155pub fn named_key_type() -> CLType {
157 CLType::Tuple2([Box::new(CLType::String), Box::new(CLType::Key)])
158}
159
160impl CLType {
161 pub(crate) fn append_bytes(&self, stream: &mut Vec<u8>) -> Result<(), bytesrepr::Error> {
162 match self {
163 CLType::Bool => stream.push(CL_TYPE_TAG_BOOL),
164 CLType::I32 => stream.push(CL_TYPE_TAG_I32),
165 CLType::I64 => stream.push(CL_TYPE_TAG_I64),
166 CLType::U8 => stream.push(CL_TYPE_TAG_U8),
167 CLType::U32 => stream.push(CL_TYPE_TAG_U32),
168 CLType::U64 => stream.push(CL_TYPE_TAG_U64),
169 CLType::U128 => stream.push(CL_TYPE_TAG_U128),
170 CLType::U256 => stream.push(CL_TYPE_TAG_U256),
171 CLType::U512 => stream.push(CL_TYPE_TAG_U512),
172 CLType::Unit => stream.push(CL_TYPE_TAG_UNIT),
173 CLType::String => stream.push(CL_TYPE_TAG_STRING),
174 CLType::Key => stream.push(CL_TYPE_TAG_KEY),
175 CLType::URef => stream.push(CL_TYPE_TAG_UREF),
176 CLType::PublicKey => stream.push(CL_TYPE_TAG_PUBLIC_KEY),
177 CLType::Option(cl_type) => {
178 stream.push(CL_TYPE_TAG_OPTION);
179 cl_type.append_bytes(stream)?;
180 }
181 CLType::List(cl_type) => {
182 stream.push(CL_TYPE_TAG_LIST);
183 cl_type.append_bytes(stream)?;
184 }
185 CLType::ByteArray(len) => {
186 stream.push(CL_TYPE_TAG_BYTE_ARRAY);
187 stream.append(&mut len.to_bytes()?);
188 }
189 CLType::Result { ok, err } => {
190 stream.push(CL_TYPE_TAG_RESULT);
191 ok.append_bytes(stream)?;
192 err.append_bytes(stream)?;
193 }
194 CLType::Map { key, value } => {
195 stream.push(CL_TYPE_TAG_MAP);
196 key.append_bytes(stream)?;
197 value.append_bytes(stream)?;
198 }
199 CLType::Tuple1(cl_type_array) => {
200 serialize_cl_tuple_type(CL_TYPE_TAG_TUPLE1, cl_type_array, stream)?
201 }
202 CLType::Tuple2(cl_type_array) => {
203 serialize_cl_tuple_type(CL_TYPE_TAG_TUPLE2, cl_type_array, stream)?
204 }
205 CLType::Tuple3(cl_type_array) => {
206 serialize_cl_tuple_type(CL_TYPE_TAG_TUPLE3, cl_type_array, stream)?
207 }
208 CLType::Any => stream.push(CL_TYPE_TAG_ANY),
209 }
210 Ok(())
211 }
212}
213
214impl FromBytes for CLType {
215 fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> {
216 depth_limited_from_bytes(0, bytes)
217 }
218}
219
220fn depth_limited_from_bytes(depth: u8, bytes: &[u8]) -> Result<(CLType, &[u8]), bytesrepr::Error> {
221 if depth >= CL_TYPE_RECURSION_DEPTH {
222 return Err(bytesrepr::Error::ExceededRecursionDepth);
223 }
224 let depth = depth + 1;
225 let (tag, remainder) = u8::from_bytes(bytes)?;
226 match tag {
227 CL_TYPE_TAG_BOOL => Ok((CLType::Bool, remainder)),
228 CL_TYPE_TAG_I32 => Ok((CLType::I32, remainder)),
229 CL_TYPE_TAG_I64 => Ok((CLType::I64, remainder)),
230 CL_TYPE_TAG_U8 => Ok((CLType::U8, remainder)),
231 CL_TYPE_TAG_U32 => Ok((CLType::U32, remainder)),
232 CL_TYPE_TAG_U64 => Ok((CLType::U64, remainder)),
233 CL_TYPE_TAG_U128 => Ok((CLType::U128, remainder)),
234 CL_TYPE_TAG_U256 => Ok((CLType::U256, remainder)),
235 CL_TYPE_TAG_U512 => Ok((CLType::U512, remainder)),
236 CL_TYPE_TAG_UNIT => Ok((CLType::Unit, remainder)),
237 CL_TYPE_TAG_STRING => Ok((CLType::String, remainder)),
238 CL_TYPE_TAG_KEY => Ok((CLType::Key, remainder)),
239 CL_TYPE_TAG_UREF => Ok((CLType::URef, remainder)),
240 CL_TYPE_TAG_PUBLIC_KEY => Ok((CLType::PublicKey, remainder)),
241 CL_TYPE_TAG_OPTION => {
242 let (inner_type, remainder) = depth_limited_from_bytes(depth, remainder)?;
243 let cl_type = CLType::Option(Box::new(inner_type));
244 Ok((cl_type, remainder))
245 }
246 CL_TYPE_TAG_LIST => {
247 let (inner_type, remainder) = depth_limited_from_bytes(depth, remainder)?;
248 let cl_type = CLType::List(Box::new(inner_type));
249 Ok((cl_type, remainder))
250 }
251 CL_TYPE_TAG_BYTE_ARRAY => {
252 let (len, remainder) = u32::from_bytes(remainder)?;
253 let cl_type = CLType::ByteArray(len);
254 Ok((cl_type, remainder))
255 }
256 CL_TYPE_TAG_RESULT => {
257 let (ok_type, remainder) = depth_limited_from_bytes(depth, remainder)?;
258 let (err_type, remainder) = depth_limited_from_bytes(depth, remainder)?;
259 let cl_type = CLType::Result {
260 ok: Box::new(ok_type),
261 err: Box::new(err_type),
262 };
263 Ok((cl_type, remainder))
264 }
265 CL_TYPE_TAG_MAP => {
266 let (key_type, remainder) = depth_limited_from_bytes(depth, remainder)?;
267 let (value_type, remainder) = depth_limited_from_bytes(depth, remainder)?;
268 let cl_type = CLType::Map {
269 key: Box::new(key_type),
270 value: Box::new(value_type),
271 };
272 Ok((cl_type, remainder))
273 }
274 CL_TYPE_TAG_TUPLE1 => {
275 let (mut inner_types, remainder) = parse_cl_tuple_types(depth, 1, remainder)?;
276 let cl_type = CLType::Tuple1([inner_types.pop_front().unwrap()]);
279 Ok((cl_type, remainder))
280 }
281 CL_TYPE_TAG_TUPLE2 => {
282 let (mut inner_types, remainder) = parse_cl_tuple_types(depth, 2, remainder)?;
283 let cl_type = CLType::Tuple2([
286 inner_types.pop_front().unwrap(),
287 inner_types.pop_front().unwrap(),
288 ]);
289 Ok((cl_type, remainder))
290 }
291 CL_TYPE_TAG_TUPLE3 => {
292 let (mut inner_types, remainder) = parse_cl_tuple_types(depth, 3, remainder)?;
293 let cl_type = CLType::Tuple3([
296 inner_types.pop_front().unwrap(),
297 inner_types.pop_front().unwrap(),
298 inner_types.pop_front().unwrap(),
299 ]);
300 Ok((cl_type, remainder))
301 }
302 CL_TYPE_TAG_ANY => Ok((CLType::Any, remainder)),
303 _ => Err(bytesrepr::Error::Formatting),
304 }
305}
306
307fn serialize_cl_tuple_type<'a, T: IntoIterator<Item = &'a Box<CLType>>>(
308 tag: u8,
309 cl_type_array: T,
310 stream: &mut Vec<u8>,
311) -> Result<(), bytesrepr::Error> {
312 stream.push(tag);
313 for cl_type in cl_type_array {
314 cl_type.append_bytes(stream)?;
315 }
316 Ok(())
317}
318
319fn parse_cl_tuple_types(
320 depth: u8,
321 count: usize,
322 mut bytes: &[u8],
323) -> Result<(VecDeque<Box<CLType>>, &[u8]), bytesrepr::Error> {
324 let mut cl_types = VecDeque::with_capacity(count);
325 for _ in 0..count {
326 let (cl_type, remainder) = depth_limited_from_bytes(depth, bytes)?;
327 cl_types.push_back(Box::new(cl_type));
328 bytes = remainder;
329 }
330
331 Ok((cl_types, bytes))
332}
333
334fn serialized_length_of_cl_tuple_type<'a, T: IntoIterator<Item = &'a Box<CLType>>>(
335 cl_type_array: T,
336) -> usize {
337 cl_type_array
338 .into_iter()
339 .map(|cl_type| cl_type.serialized_length())
340 .sum()
341}
342
343pub trait CLTyped {
345 fn cl_type() -> CLType;
347}
348
349impl CLTyped for bool {
350 fn cl_type() -> CLType {
351 CLType::Bool
352 }
353}
354
355impl CLTyped for i32 {
356 fn cl_type() -> CLType {
357 CLType::I32
358 }
359}
360
361impl CLTyped for i64 {
362 fn cl_type() -> CLType {
363 CLType::I64
364 }
365}
366
367impl CLTyped for u8 {
368 fn cl_type() -> CLType {
369 CLType::U8
370 }
371}
372
373impl CLTyped for u32 {
374 fn cl_type() -> CLType {
375 CLType::U32
376 }
377}
378
379impl CLTyped for u64 {
380 fn cl_type() -> CLType {
381 CLType::U64
382 }
383}
384
385impl CLTyped for U128 {
386 fn cl_type() -> CLType {
387 CLType::U128
388 }
389}
390
391impl CLTyped for U256 {
392 fn cl_type() -> CLType {
393 CLType::U256
394 }
395}
396
397impl CLTyped for U512 {
398 fn cl_type() -> CLType {
399 CLType::U512
400 }
401}
402
403impl CLTyped for () {
404 fn cl_type() -> CLType {
405 CLType::Unit
406 }
407}
408
409impl CLTyped for String {
410 fn cl_type() -> CLType {
411 CLType::String
412 }
413}
414
415impl CLTyped for &str {
416 fn cl_type() -> CLType {
417 CLType::String
418 }
419}
420
421impl CLTyped for Key {
422 fn cl_type() -> CLType {
423 CLType::Key
424 }
425}
426
427impl CLTyped for URef {
428 fn cl_type() -> CLType {
429 CLType::URef
430 }
431}
432
433impl<T: CLTyped> CLTyped for Option<T> {
434 fn cl_type() -> CLType {
435 CLType::Option(Box::new(T::cl_type()))
436 }
437}
438
439impl<T: CLTyped> CLTyped for Vec<T> {
440 fn cl_type() -> CLType {
441 CLType::List(Box::new(T::cl_type()))
442 }
443}
444
445impl<T: CLTyped> CLTyped for BTreeSet<T> {
446 fn cl_type() -> CLType {
447 CLType::List(Box::new(T::cl_type()))
448 }
449}
450
451impl<T: CLTyped> CLTyped for &T {
452 fn cl_type() -> CLType {
453 T::cl_type()
454 }
455}
456
457impl<const COUNT: usize> CLTyped for [u8; COUNT] {
458 fn cl_type() -> CLType {
459 CLType::ByteArray(COUNT as u32)
460 }
461}
462
463impl<T: CLTyped, E: CLTyped> CLTyped for Result<T, E> {
464 fn cl_type() -> CLType {
465 let ok = Box::new(T::cl_type());
466 let err = Box::new(E::cl_type());
467 CLType::Result { ok, err }
468 }
469}
470
471impl<K: CLTyped, V: CLTyped> CLTyped for BTreeMap<K, V> {
472 fn cl_type() -> CLType {
473 let key = Box::new(K::cl_type());
474 let value = Box::new(V::cl_type());
475 CLType::Map { key, value }
476 }
477}
478
479impl<T1: CLTyped> CLTyped for (T1,) {
480 fn cl_type() -> CLType {
481 CLType::Tuple1([Box::new(T1::cl_type())])
482 }
483}
484
485impl<T1: CLTyped, T2: CLTyped> CLTyped for (T1, T2) {
486 fn cl_type() -> CLType {
487 CLType::Tuple2([Box::new(T1::cl_type()), Box::new(T2::cl_type())])
488 }
489}
490
491impl<T1: CLTyped, T2: CLTyped, T3: CLTyped> CLTyped for (T1, T2, T3) {
492 fn cl_type() -> CLType {
493 CLType::Tuple3([
494 Box::new(T1::cl_type()),
495 Box::new(T2::cl_type()),
496 Box::new(T3::cl_type()),
497 ])
498 }
499}
500
501impl<T: CLTyped> CLTyped for Ratio<T> {
502 fn cl_type() -> CLType {
503 <(T, T)>::cl_type()
504 }
505}
506
507#[cfg(test)]
508mod tests {
509 use std::{fmt::Debug, iter, string::ToString};
510
511 use super::*;
512 use crate::{
513 bytesrepr::{FromBytes, ToBytes},
514 AccessRights, CLValue,
515 };
516
517 fn round_trip<T: CLTyped + FromBytes + ToBytes + PartialEq + Debug + Clone>(value: &T) {
518 let cl_value = CLValue::from_t(value.clone()).unwrap();
519
520 let serialized_cl_value = cl_value.to_bytes().unwrap();
521 assert_eq!(serialized_cl_value.len(), cl_value.serialized_length());
522 let parsed_cl_value: CLValue = bytesrepr::deserialize(serialized_cl_value).unwrap();
523 assert_eq!(cl_value, parsed_cl_value);
524
525 let parsed_value = CLValue::into_t(cl_value).unwrap();
526 assert_eq!(*value, parsed_value);
527 }
528
529 #[test]
530 fn bool_should_work() {
531 round_trip(&true);
532 round_trip(&false);
533 }
534
535 #[test]
536 fn u8_should_work() {
537 round_trip(&1u8);
538 }
539
540 #[test]
541 fn u32_should_work() {
542 round_trip(&1u32);
543 }
544
545 #[test]
546 fn i32_should_work() {
547 round_trip(&-1i32);
548 }
549
550 #[test]
551 fn u64_should_work() {
552 round_trip(&1u64);
553 }
554
555 #[test]
556 fn i64_should_work() {
557 round_trip(&-1i64);
558 }
559
560 #[test]
561 fn u128_should_work() {
562 round_trip(&U128::one());
563 }
564
565 #[test]
566 fn u256_should_work() {
567 round_trip(&U256::one());
568 }
569
570 #[test]
571 fn u512_should_work() {
572 round_trip(&U512::one());
573 }
574
575 #[test]
576 fn unit_should_work() {
577 round_trip(&());
578 }
579
580 #[test]
581 fn string_should_work() {
582 round_trip(&String::from("abc"));
583 }
584
585 #[test]
586 fn key_should_work() {
587 let key = Key::URef(URef::new([0u8; 32], AccessRights::READ_ADD_WRITE));
588 round_trip(&key);
589 }
590
591 #[test]
592 fn uref_should_work() {
593 let uref = URef::new([0u8; 32], AccessRights::READ_ADD_WRITE);
594 round_trip(&uref);
595 }
596
597 #[test]
598 fn option_of_cl_type_should_work() {
599 let x: Option<i32> = Some(-1);
600 let y: Option<i32> = None;
601
602 round_trip(&x);
603 round_trip(&y);
604 }
605
606 #[test]
607 fn vec_of_cl_type_should_work() {
608 let vec = vec![String::from("a"), String::from("b")];
609 round_trip(&vec);
610 }
611
612 #[test]
613 #[allow(clippy::cognitive_complexity)]
614 fn small_array_of_u8_should_work() {
615 macro_rules! test_small_array {
616 ($($N:literal)+) => {
617 $(
618 let mut array: [u8; $N] = Default::default();
619 for i in 0..$N {
620 array[i] = i as u8;
621 }
622 round_trip(&array);
623 )+
624 }
625 }
626
627 test_small_array! {
628 1 2 3 4 5 6 7 8 9
629 10 11 12 13 14 15 16 17 18 19
630 20 21 22 23 24 25 26 27 28 29
631 30 31 32
632 }
633 }
634
635 #[test]
636 fn large_array_of_cl_type_should_work() {
637 macro_rules! test_large_array {
638 ($($N:literal)+) => {
639 $(
640 let array = {
641 let mut tmp = [0u8; $N];
642 for i in 0..$N {
643 tmp[i] = i as u8;
644 }
645 tmp
646 };
647
648 let cl_value = CLValue::from_t(array.clone()).unwrap();
649
650 let serialized_cl_value = cl_value.to_bytes().unwrap();
651 let parsed_cl_value: CLValue = bytesrepr::deserialize(serialized_cl_value).unwrap();
652 assert_eq!(cl_value, parsed_cl_value);
653
654 let parsed_value: [u8; $N] = CLValue::into_t(cl_value).unwrap();
655 for i in 0..$N {
656 assert_eq!(array[i], parsed_value[i]);
657 }
658 )+
659 }
660 }
661
662 test_large_array! { 64 128 256 512 }
663 }
664
665 #[test]
666 fn result_of_cl_type_should_work() {
667 let x: Result<(), String> = Ok(());
668 let y: Result<(), String> = Err(String::from("Hello, world!"));
669
670 round_trip(&x);
671 round_trip(&y);
672 }
673
674 #[test]
675 fn map_of_cl_type_should_work() {
676 let mut map: BTreeMap<String, u64> = BTreeMap::new();
677 map.insert(String::from("abc"), 1);
678 map.insert(String::from("xyz"), 2);
679
680 round_trip(&map);
681 }
682
683 #[test]
684 fn tuple_1_should_work() {
685 let x = (-1i32,);
686
687 round_trip(&x);
688 }
689
690 #[test]
691 fn tuple_2_should_work() {
692 let x = (-1i32, String::from("a"));
693
694 round_trip(&x);
695 }
696
697 #[test]
698 fn tuple_3_should_work() {
699 let x = (-1i32, 1u32, String::from("a"));
700
701 round_trip(&x);
702 }
703
704 #[test]
705 fn parsing_nested_tuple_1_cltype_should_not_stack_overflow() {
706 for i in 1..1000 {
711 let bytes = iter::repeat(CL_TYPE_TAG_TUPLE1)
712 .take(i)
713 .chain(iter::once(CL_TYPE_TAG_UNIT))
714 .collect();
715 match bytesrepr::deserialize(bytes) {
716 Ok(parsed_cltype) => assert!(matches!(parsed_cltype, CLType::Tuple1(_))),
717 Err(error) => assert_eq!(error, bytesrepr::Error::ExceededRecursionDepth),
718 }
719 }
720 }
721
722 #[test]
723 fn parsing_nested_tuple_1_value_should_not_stack_overflow() {
724 for i in 1..1000 {
729 let bytes = iter::repeat(0)
730 .take(4)
731 .chain(iter::repeat(CL_TYPE_TAG_TUPLE1).take(i))
732 .chain(iter::once(CL_TYPE_TAG_UNIT))
733 .collect();
734 match bytesrepr::deserialize::<CLValue>(bytes) {
735 Ok(parsed_clvalue) => {
736 assert!(matches!(parsed_clvalue.cl_type(), CLType::Tuple1(_)))
737 }
738 Err(error) => assert_eq!(error, bytesrepr::Error::ExceededRecursionDepth),
739 }
740 }
741 }
742
743 #[test]
744 fn any_should_work() {
745 #[derive(PartialEq, Debug, Clone)]
746 struct Any(String);
747
748 impl CLTyped for Any {
749 fn cl_type() -> CLType {
750 CLType::Any
751 }
752 }
753
754 impl ToBytes for Any {
755 fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
756 self.0.to_bytes()
757 }
758
759 fn serialized_length(&self) -> usize {
760 self.0.serialized_length()
761 }
762 }
763
764 impl FromBytes for Any {
765 fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> {
766 let (inner, remainder) = String::from_bytes(bytes)?;
767 Ok((Any(inner), remainder))
768 }
769 }
770
771 let any = Any("Any test".to_string());
772 round_trip(&any);
773 }
774
775 #[test]
776 fn should_have_cltype_of_ref_to_cltyped() {
777 assert_eq!(<Vec<&u64>>::cl_type(), <Vec<u64>>::cl_type())
778 }
779}