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