Skip to main content

pallas_primitives/
plutus_data.rs

1use crate::KeyValuePairs;
2use pallas_codec::utils::Int;
3use pallas_codec::{
4    minicbor::{
5        self,
6        data::{IanaTag, Tag},
7        Encode,
8    },
9    utils::MaybeIndefArray,
10};
11use serde::{Deserialize, Serialize};
12use std::cmp::Ordering;
13use std::{fmt, ops::Deref};
14
15#[derive(Serialize, Deserialize, Debug, Clone)]
16pub enum PlutusData {
17    Constr(Constr<PlutusData>),
18    Map(KeyValuePairs<PlutusData, PlutusData>),
19    Array(MaybeIndefArray<PlutusData>),
20    BigInt(BigInt),
21    BoundedBytes(BoundedBytes),
22}
23
24impl Eq for PlutusData {}
25
26impl PartialEq for PlutusData {
27    fn eq(&self, other: &Self) -> bool {
28        self.cmp(other) == Ordering::Equal
29    }
30}
31
32impl PartialOrd for PlutusData {
33    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
34        Some(self.cmp(other))
35    }
36}
37
38impl Ord for PlutusData {
39    fn cmp(&self, other: &Self) -> Ordering {
40        match (self, other) {
41            (Self::Constr(left), Self::Constr(right)) => left.cmp(right),
42            (Self::Constr(..), _) => Ordering::Less,
43            (_, Self::Constr(..)) => Ordering::Greater,
44            (Self::Map(left), Self::Map(right)) => left.deref().cmp(right.deref()),
45            (Self::Map(..), _) => Ordering::Less,
46            (_, Self::Map(..)) => Ordering::Greater,
47            (Self::Array(left), Self::Array(right)) => left.deref().cmp(right.deref()),
48            (Self::Array(..), _) => Ordering::Less,
49            (_, Self::Array(..)) => Ordering::Greater,
50            (Self::BigInt(left), Self::BigInt(right)) => left.cmp(right),
51            (Self::BigInt(..), _) => Ordering::Less,
52            (_, Self::BigInt(..)) => Ordering::Greater,
53            (Self::BoundedBytes(left), Self::BoundedBytes(right)) => left.cmp(right),
54        }
55    }
56}
57
58impl<'b, C> minicbor::decode::Decode<'b, C> for PlutusData {
59    fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
60        let type_ = d.datatype()?;
61
62        match type_ {
63            minicbor::data::Type::Tag => {
64                let mut probe = d.probe();
65                let tag = probe.tag()?;
66
67                if tag == IanaTag::PosBignum.tag() || tag == IanaTag::NegBignum.tag() {
68                    Ok(Self::BigInt(d.decode_with(ctx)?))
69                } else {
70                    match tag.as_u64() {
71                        (121..=127) | (1280..=1400) | 102 => Ok(Self::Constr(d.decode_with(ctx)?)),
72                        _ => Err(minicbor::decode::Error::message(
73                            "unknown tag for plutus data tag",
74                        )),
75                    }
76                }
77            }
78            minicbor::data::Type::U8
79            | minicbor::data::Type::U16
80            | minicbor::data::Type::U32
81            | minicbor::data::Type::U64
82            | minicbor::data::Type::I8
83            | minicbor::data::Type::I16
84            | minicbor::data::Type::I32
85            | minicbor::data::Type::I64
86            | minicbor::data::Type::Int => Ok(Self::BigInt(d.decode_with(ctx)?)),
87            minicbor::data::Type::Map | minicbor::data::Type::MapIndef => {
88                Ok(Self::Map(d.decode_with(ctx)?))
89            }
90            minicbor::data::Type::Bytes => Ok(Self::BoundedBytes(d.decode_with(ctx)?)),
91            minicbor::data::Type::BytesIndef => {
92                let mut full = Vec::new();
93
94                for slice in d.bytes_iter()? {
95                    full.extend(slice?);
96                }
97
98                Ok(Self::BoundedBytes(BoundedBytes::from(full)))
99            }
100            minicbor::data::Type::Array | minicbor::data::Type::ArrayIndef => {
101                Ok(Self::Array(d.decode_with(ctx)?))
102            }
103
104            any => Err(minicbor::decode::Error::message(format!(
105                "bad cbor data type ({any:?}) for plutus data"
106            ))),
107        }
108    }
109}
110
111impl<C> minicbor::encode::Encode<C> for PlutusData {
112    fn encode<W: minicbor::encode::Write>(
113        &self,
114        e: &mut minicbor::Encoder<W>,
115        ctx: &mut C,
116    ) -> Result<(), minicbor::encode::Error<W::Error>> {
117        match self {
118            Self::Constr(a) => {
119                e.encode_with(a, ctx)?;
120            }
121            Self::Map(a) => {
122                e.encode_with(a, ctx)?;
123            }
124            Self::BigInt(a) => {
125                e.encode_with(a, ctx)?;
126            }
127            Self::BoundedBytes(a) => {
128                e.encode_with(a, ctx)?;
129            }
130            Self::Array(a) => {
131                e.encode_with(a, ctx)?;
132            }
133        };
134
135        Ok(())
136    }
137}
138
139/*
140big_int = int / big_uint / big_nint ; New
141big_uint = #6.2(bounded_bytes) ; New
142big_nint = #6.3(bounded_bytes) ; New
143 */
144
145#[derive(Serialize, Deserialize, Debug, Clone)]
146pub enum BigInt {
147    Int(Int),
148    BigUInt(BoundedBytes),
149    BigNInt(BoundedBytes),
150}
151
152impl Eq for BigInt {}
153
154impl PartialEq for BigInt {
155    fn eq(&self, other: &Self) -> bool {
156        self.cmp(other) == Ordering::Equal
157    }
158}
159
160impl PartialOrd for BigInt {
161    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
162        Some(self.cmp(other))
163    }
164}
165
166impl Ord for BigInt {
167    fn cmp(&self, other: &Self) -> Ordering {
168        fn to_bytes(i: &BigInt) -> (bool, Vec<u8>) {
169            match i {
170                BigInt::Int(i) => {
171                    let i = Into::<i128>::into(*i);
172                    (
173                        i < 0,
174                        i.abs()
175                            .to_be_bytes()
176                            .into_iter()
177                            .skip_while(|b| b == &0)
178                            .collect(),
179                    )
180                }
181                BigInt::BigUInt(bs) => {
182                    (false, bs.iter().skip_while(|b| b == &&0).copied().collect())
183                }
184                BigInt::BigNInt(bs) => {
185                    (true, bs.iter().skip_while(|b| b == &&0).copied().collect())
186                }
187            }
188        }
189
190        let (left_is_negative, left) = to_bytes(self);
191
192        let (right_is_negative, right) = to_bytes(other);
193
194        if left.is_empty() && right.is_empty() {
195            return Ordering::Equal;
196        }
197
198        if left_is_negative && !right_is_negative {
199            return Ordering::Less;
200        }
201
202        if !left_is_negative && right_is_negative {
203            return Ordering::Greater;
204        }
205
206        let when_positives = match left.len().cmp(&right.len()) {
207            Ordering::Equal => left.cmp(&right),
208            ordering => ordering,
209        };
210
211        if left_is_negative && right_is_negative {
212            when_positives.reverse()
213        } else {
214            when_positives
215        }
216    }
217}
218
219impl<'b, C> minicbor::decode::Decode<'b, C> for BigInt {
220    fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
221        let datatype = d.datatype()?;
222
223        match datatype {
224            minicbor::data::Type::U8
225            | minicbor::data::Type::U16
226            | minicbor::data::Type::U32
227            | minicbor::data::Type::U64
228            | minicbor::data::Type::I8
229            | minicbor::data::Type::I16
230            | minicbor::data::Type::I32
231            | minicbor::data::Type::I64
232            | minicbor::data::Type::Int => Ok(Self::Int(d.decode_with(ctx)?)),
233            minicbor::data::Type::Tag => {
234                let tag = d.tag()?;
235                if tag == IanaTag::PosBignum.tag() {
236                    Ok(Self::BigUInt(d.decode_with(ctx)?))
237                } else if tag == IanaTag::NegBignum.tag() {
238                    Ok(Self::BigNInt(d.decode_with(ctx)?))
239                } else {
240                    Err(minicbor::decode::Error::message(
241                        "invalid cbor tag for big int",
242                    ))
243                }
244            }
245            _ => Err(minicbor::decode::Error::message(
246                "invalid cbor data type for big int",
247            )),
248        }
249    }
250}
251
252impl<C> minicbor::encode::Encode<C> for BigInt {
253    fn encode<W: minicbor::encode::Write>(
254        &self,
255        e: &mut minicbor::Encoder<W>,
256        ctx: &mut C,
257    ) -> Result<(), minicbor::encode::Error<W::Error>> {
258        match self {
259            BigInt::Int(x) => {
260                e.encode_with(x, ctx)?;
261            }
262            BigInt::BigUInt(x) => {
263                e.tag(IanaTag::PosBignum)?;
264                e.encode_with(x, ctx)?;
265            }
266            BigInt::BigNInt(x) => {
267                e.tag(IanaTag::NegBignum)?;
268                e.encode_with(x, ctx)?;
269            }
270        };
271
272        Ok(())
273    }
274}
275
276#[derive(Serialize, Deserialize, Debug, Clone)]
277pub struct Constr<A> {
278    pub tag: u64,
279    pub any_constructor: Option<u64>,
280    pub fields: MaybeIndefArray<A>,
281}
282
283impl<A: Ord> Eq for Constr<A> {}
284
285impl<A: Ord> PartialEq for Constr<A> {
286    fn eq(&self, other: &Self) -> bool {
287        self.cmp(other) == Ordering::Equal
288    }
289}
290
291impl<A: Ord> PartialOrd for Constr<A> {
292    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
293        Some(self.cmp(other))
294    }
295}
296
297impl<A: Ord> Ord for Constr<A> {
298    fn cmp(&self, other: &Self) -> Ordering {
299        match self.constr_index().cmp(&other.constr_index()) {
300            Ordering::Equal => self.fields.deref().cmp(other.fields.deref()),
301            ordering => ordering,
302        }
303    }
304}
305
306impl<A> Constr<A> {
307    pub fn constr_index(&self) -> u64 {
308        match self.tag {
309            121..=127 => self.tag - 121,
310            1280..=1400 => self.tag - 1280 + 7,
311            102 => self
312                .any_constructor
313                .unwrap_or_else(|| panic!("malformed Constr: missing 'any_constructor'")),
314            tag => panic!("malformed Constr: invalid tag {tag:?}"),
315        }
316    }
317}
318
319impl<'b, C, A> minicbor::decode::Decode<'b, C> for Constr<A>
320where
321    A: minicbor::decode::Decode<'b, C>,
322{
323    fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
324        let tag = d.tag()?;
325        let x = tag.as_u64();
326        match x {
327            121..=127 | 1280..=1400 => Ok(Constr {
328                tag: x,
329                fields: d.decode_with(ctx)?,
330                any_constructor: None,
331            }),
332            102 => {
333                d.array()?;
334
335                Ok(Constr {
336                    tag: x,
337                    any_constructor: Some(d.decode_with(ctx)?),
338                    fields: d.decode_with(ctx)?,
339                })
340            }
341            _ => Err(minicbor::decode::Error::message(
342                "bad tag code for plutus data",
343            )),
344        }
345    }
346}
347
348impl<C, A> minicbor::encode::Encode<C> for Constr<A>
349where
350    A: minicbor::encode::Encode<C>,
351{
352    fn encode<W: minicbor::encode::Write>(
353        &self,
354        e: &mut minicbor::Encoder<W>,
355        ctx: &mut C,
356    ) -> Result<(), minicbor::encode::Error<W::Error>> {
357        e.tag(Tag::new(self.tag))?;
358
359        match self.tag {
360            102 => {
361                let x = (self.any_constructor.unwrap_or_default(), &self.fields);
362                e.encode_with(x, ctx)?;
363                Ok(())
364            }
365            _ => {
366                e.encode_with(&self.fields, ctx)?;
367                Ok(())
368            }
369        }
370    }
371}
372
373/// Defined to encode PlutusData bytestring as it is done in the canonical
374/// plutus implementation
375#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
376#[serde(into = "String")]
377#[serde(try_from = "String")]
378pub struct BoundedBytes(Vec<u8>);
379
380impl From<Vec<u8>> for BoundedBytes {
381    fn from(xs: Vec<u8>) -> Self {
382        BoundedBytes(xs)
383    }
384}
385
386impl From<BoundedBytes> for Vec<u8> {
387    fn from(b: BoundedBytes) -> Self {
388        b.0
389    }
390}
391
392impl Deref for BoundedBytes {
393    type Target = Vec<u8>;
394
395    fn deref(&self) -> &Self::Target {
396        &self.0
397    }
398}
399
400impl TryFrom<String> for BoundedBytes {
401    type Error = hex::FromHexError;
402
403    fn try_from(value: String) -> Result<Self, Self::Error> {
404        let v = hex::decode(value)?;
405        Ok(BoundedBytes(v))
406    }
407}
408
409impl From<BoundedBytes> for String {
410    fn from(b: BoundedBytes) -> Self {
411        hex::encode(b.deref())
412    }
413}
414
415impl fmt::Display for BoundedBytes {
416    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
417        let bytes: Vec<u8> = self.clone().into();
418
419        f.write_str(&hex::encode(bytes))
420    }
421}
422
423impl<C> Encode<C> for BoundedBytes {
424    fn encode<W: minicbor::encode::Write>(
425        &self,
426        e: &mut minicbor::Encoder<W>,
427        _: &mut C,
428    ) -> Result<(), minicbor::encode::Error<W::Error>> {
429        // we match the haskell implementation by encoding bytestrings longer than 64
430        // bytes as indefinite lists of bytes
431        const CHUNK_SIZE: usize = 64;
432        let bs: &Vec<u8> = self.deref();
433        if bs.len() <= 64 {
434            e.bytes(bs)?;
435        } else {
436            e.begin_bytes()?;
437            for b in bs.chunks(CHUNK_SIZE) {
438                e.bytes(b)?;
439            }
440            e.end()?;
441        }
442        Ok(())
443    }
444}
445
446impl<'b, C> minicbor::decode::Decode<'b, C> for BoundedBytes {
447    fn decode(d: &mut minicbor::Decoder<'b>, _: &mut C) -> Result<Self, minicbor::decode::Error> {
448        let mut res = Vec::new();
449        for chunk in d.bytes_iter()? {
450            let bs = chunk?;
451            res.extend_from_slice(bs);
452        }
453        Ok(BoundedBytes::from(res))
454    }
455}
456
457#[cfg(test)]
458mod tests {
459    use super::*;
460    use crate::{BigInt, BoundedBytes, Constr, KeyValuePairs, MaybeIndefArray};
461    use proptest::{prelude::*, strategy::Just};
462    use test_case::test_case;
463
464    prop_compose! {
465        pub(crate) fn any_bounded_bytes()(
466            bytes in any::<Vec<u8>>(),
467        ) -> BoundedBytes {
468            BoundedBytes::from(bytes)
469        }
470    }
471
472    pub(crate) fn any_bigint() -> impl Strategy<Value = BigInt> {
473        prop_oneof![
474            any::<i64>().prop_map(|i| BigInt::Int(i.into())),
475            any_bounded_bytes().prop_map(BigInt::BigUInt),
476            any_bounded_bytes().prop_map(BigInt::BigNInt),
477        ]
478    }
479
480    fn any_constr(depth: u8) -> impl Strategy<Value = Constr<PlutusData>> {
481        let any_constr_tag = prop_oneof![
482            (Just(102), any::<u64>().prop_map(Some)),
483            (121_u64..=127, Just(None)),
484            (1280_u64..=1400, Just(None))
485        ];
486
487        let any_fields = prop::collection::vec(any_plutus_data(depth - 1), 0..depth as usize);
488
489        (any_constr_tag, any_fields, any::<bool>()).prop_map(
490            |((tag, any_constructor), fields, is_def)| Constr {
491                tag,
492                any_constructor,
493                fields: if is_def {
494                    MaybeIndefArray::Def(fields)
495                } else {
496                    MaybeIndefArray::Indef(fields)
497                },
498            },
499        )
500    }
501
502    fn any_plutus_data(depth: u8) -> BoxedStrategy<PlutusData> {
503        let int = any_bigint().prop_map(PlutusData::BigInt);
504
505        let bytes = any_bounded_bytes().prop_map(PlutusData::BoundedBytes);
506
507        if depth > 0 {
508            let constr = any_constr(depth).prop_map(PlutusData::Constr);
509
510            let array = (
511                any::<bool>(),
512                prop::collection::vec(any_plutus_data(depth - 1), 0..depth as usize),
513            )
514                .prop_map(|(is_def, xs)| {
515                    PlutusData::Array(if is_def {
516                        MaybeIndefArray::Def(xs)
517                    } else {
518                        MaybeIndefArray::Indef(xs)
519                    })
520                });
521
522            let map = (
523                any::<bool>(),
524                prop::collection::vec(
525                    (any_plutus_data(depth - 1), any_plutus_data(depth - 1)),
526                    0..depth as usize,
527                ),
528            )
529                .prop_map(|(is_def, kvs)| {
530                    PlutusData::Map(if is_def {
531                        KeyValuePairs::Def(kvs)
532                    } else {
533                        KeyValuePairs::Indef(kvs)
534                    })
535                });
536
537            prop_oneof![int, bytes, constr, array, map].boxed()
538        } else {
539            prop_oneof![int, bytes].boxed()
540        }
541    }
542
543    proptest! {
544        #[test]
545        fn cbor_roundtrip(original_data in any_plutus_data(3)) {
546            let bytes = minicbor::to_vec(&original_data).unwrap();
547            let data: PlutusData = minicbor::decode(&bytes).unwrap();
548            assert_eq!(data, original_data);
549        }
550    }
551
552    /// Swap some Def to Indef (or vice-versa), in an existing PlutusData. The
553    /// 'depth' parameter is used to avoid always changing the outer-most
554    /// layer, but also try to alter some nested element, if any.
555    fn alter_any_encoding(data: PlutusData, depth: usize) -> PlutusData {
556        let alter_kvs = |kvs: Vec<(PlutusData, PlutusData)>| -> Vec<(PlutusData, PlutusData)> {
557            kvs.into_iter()
558                .map(|(k, v)| {
559                    (
560                        alter_any_encoding(k, depth - 1),
561                        alter_any_encoding(v, depth - 1),
562                    )
563                })
564                .collect()
565        };
566
567        let alter_vec = |xs: Vec<PlutusData>| -> Vec<PlutusData> {
568            xs.into_iter()
569                .map(|x| alter_any_encoding(x, depth - 1))
570                .collect()
571        };
572
573        match data {
574            PlutusData::BigInt(i) => PlutusData::BigInt(i),
575            PlutusData::BoundedBytes(bs) => PlutusData::BoundedBytes(bs),
576            PlutusData::Map(m) => PlutusData::Map(match m {
577                KeyValuePairs::Def(kvs) if depth > 1 => KeyValuePairs::Def(alter_kvs(kvs)),
578                KeyValuePairs::Def(kvs) => KeyValuePairs::Indef(kvs),
579                KeyValuePairs::Indef(kvs) if depth > 1 => KeyValuePairs::Indef(alter_kvs(kvs)),
580                KeyValuePairs::Indef(kvs) => KeyValuePairs::Def(kvs),
581            }),
582            PlutusData::Array(m) => PlutusData::Array(match m {
583                MaybeIndefArray::Def(xs) if depth > 1 => MaybeIndefArray::Def(alter_vec(xs)),
584                MaybeIndefArray::Def(xs) => MaybeIndefArray::Indef(xs),
585                MaybeIndefArray::Indef(xs) if depth > 1 => MaybeIndefArray::Indef(alter_vec(xs)),
586                MaybeIndefArray::Indef(xs) => MaybeIndefArray::Def(xs),
587            }),
588            PlutusData::Constr(Constr {
589                tag,
590                any_constructor,
591                fields,
592            }) => PlutusData::Constr(Constr {
593                tag,
594                any_constructor,
595                fields: match fields {
596                    MaybeIndefArray::Def(xs) if depth > 1 => MaybeIndefArray::Def(alter_vec(xs)),
597                    MaybeIndefArray::Def(xs) => MaybeIndefArray::Indef(xs),
598                    MaybeIndefArray::Indef(xs) if depth > 1 => {
599                        MaybeIndefArray::Indef(alter_vec(xs))
600                    }
601                    MaybeIndefArray::Indef(xs) => MaybeIndefArray::Def(xs),
602                },
603            }),
604        }
605    }
606
607    proptest! {
608        #[test]
609        fn equals_list_irrespective_of_encoding((depth, left) in (1..=3_usize, any_plutus_data(3))) {
610            let right = alter_any_encoding(left.clone(), depth);
611            assert_eq!(left, right);
612            assert_eq!(right, left);
613        }
614    }
615
616    fn int(i: i64) -> PlutusData {
617        PlutusData::BigInt(BigInt::Int(i.into()))
618    }
619
620    fn biguint(bs: &[u8]) -> PlutusData {
621        PlutusData::BigInt(BigInt::BigUInt(BoundedBytes::from(bs.to_vec())))
622    }
623
624    fn bignint(bs: &[u8]) -> PlutusData {
625        PlutusData::BigInt(BigInt::BigNInt(BoundedBytes::from(bs.to_vec())))
626    }
627
628    fn bytes(bs: &[u8]) -> PlutusData {
629        PlutusData::BoundedBytes(BoundedBytes::from(bs.to_vec()))
630    }
631
632    fn array_def(xs: &[PlutusData]) -> PlutusData {
633        PlutusData::Array(MaybeIndefArray::Def(xs.to_vec()))
634    }
635
636    fn array_indef(xs: &[PlutusData]) -> PlutusData {
637        PlutusData::Array(MaybeIndefArray::Indef(xs.to_vec()))
638    }
639
640    fn map_def(kvs: &[(PlutusData, PlutusData)]) -> PlutusData {
641        PlutusData::Map(KeyValuePairs::Def(kvs.to_vec()))
642    }
643
644    fn map_indef(kvs: &[(PlutusData, PlutusData)]) -> PlutusData {
645        PlutusData::Map(KeyValuePairs::Indef(kvs.to_vec()))
646    }
647
648    fn constr(tag: u64, fields: &[PlutusData]) -> PlutusData {
649        PlutusData::Constr(Constr {
650            tag,
651            any_constructor: None,
652            fields: MaybeIndefArray::Def(fields.to_vec()),
653        })
654    }
655
656    fn constr_any(any_constructor: u64, fields: &[PlutusData]) -> PlutusData {
657        PlutusData::Constr(Constr {
658            tag: 102,
659            any_constructor: Some(any_constructor),
660            fields: MaybeIndefArray::Def(fields.to_vec()),
661        })
662    }
663
664    // Bytes <-> ...
665    #[test_case(bytes(&[]), bytes(&[]) => Ordering::Equal)]
666    #[test_case(bytes(&[1, 2, 3]), bytes(&[4, 5, 6]) => Ordering::Less)]
667    #[test_case(bytes(&[1, 2, 3]), bytes(&[1, 2, 3]) => Ordering::Equal)]
668    #[test_case(bytes(&[4, 5, 6]), bytes(&[1, 2, 3]) => Ordering::Greater)]
669    #[test_case(bytes(&[1, 2, 3]), bytes(&[2, 2, 3]) => Ordering::Less)]
670    #[test_case(bytes(&[1, 2, 3]), bytes(&[1, 2]) => Ordering::Greater)]
671    #[test_case(bytes(&[2, 2]), bytes(&[1, 2, 3]) => Ordering::Greater)]
672    #[test_case(bytes(&[]), constr(121, &[]) => Ordering::Greater)]
673    #[test_case(bytes(&[]), map_def(&[]) => Ordering::Greater)]
674    #[test_case(bytes(&[]), map_indef(&[]) => Ordering::Greater)]
675    #[test_case(bytes(&[]), array_def(&[]) => Ordering::Greater)]
676    #[test_case(bytes(&[]), array_indef(&[]) => Ordering::Greater)]
677    #[test_case(bytes(&[]), int(0) => Ordering::Greater)]
678    // Int <-> ...
679    #[test_case(int(42), int(14) => Ordering::Greater)]
680    #[test_case(int(14), int(14) => Ordering::Equal)]
681    #[test_case(int(14), int(42) => Ordering::Less)]
682    #[test_case(int(0), int(-1) => Ordering::Greater)]
683    #[test_case(int(-2), int(-1) => Ordering::Less)]
684    #[test_case(int(0), biguint(&[0]) => Ordering::Equal)]
685    #[test_case(int(14), biguint(&[14]) => Ordering::Equal)]
686    #[test_case(int(14), biguint(&[42]) => Ordering::Less)]
687    #[test_case(biguint(&[14]), int(42) => Ordering::Less)]
688    #[test_case(biguint(&[42]), int(14) => Ordering::Greater)]
689    #[test_case(biguint(&[14, 255]), int(42) => Ordering::Greater)]
690    #[test_case(bignint(&[0]), int(0) => Ordering::Equal)]
691    #[test_case(bignint(&[14, 255]), int(-42) => Ordering::Less)]
692    #[test_case(biguint(&[]), int(0) => Ordering::Equal)]
693    #[test_case(biguint(&[0, 0, 1]), int(1) => Ordering::Equal)]
694    #[test_case(int(0), constr(121, &[]) => Ordering::Greater)]
695    #[test_case(int(0), map_def(&[]) => Ordering::Greater)]
696    #[test_case(int(0), map_indef(&[]) => Ordering::Greater)]
697    #[test_case(int(0), array_def(&[]) => Ordering::Greater)]
698    #[test_case(int(0), array_indef(&[]) => Ordering::Greater)]
699    #[test_case(int(0), bytes(&[]) => Ordering::Less)]
700    // Array <-> ...
701    #[test_case(array_def(&[]), array_def(&[]) => Ordering::Equal)]
702    #[test_case(array_def(&[]), array_indef(&[]) => Ordering::Equal)]
703    #[test_case(array_indef(&[]), array_def(&[]) => Ordering::Equal)]
704    #[test_case(array_def(&[int(14), int(42)]), array_def(&[int(14), int(42)]) => Ordering::Equal)]
705    #[test_case(array_def(&[int(14), int(42)]), array_def(&[int(15)]) => Ordering::Less)]
706    #[test_case(array_def(&[int(14), int(42)]), array_def(&[int(1), int(2), int(3)]) => Ordering::Greater)]
707    #[test_case(array_def(&[int(14), int(42)]), array_indef(&[int(14), int(42)]) => Ordering::Equal)]
708    #[test_case(array_indef(&[int(14), int(42)]), array_def(&[int(15)]) => Ordering::Less)]
709    #[test_case(array_def(&[int(14), int(42)]), array_indef(&[int(1), int(2), int(3)]) => Ordering::Greater)]
710    #[test_case(array_def(&[]), constr(121, &[]) => Ordering::Greater)]
711    #[test_case(array_def(&[]), map_def(&[]) => Ordering::Greater)]
712    #[test_case(array_def(&[]), map_indef(&[]) => Ordering::Greater)]
713    #[test_case(array_def(&[]), int(0) => Ordering::Less)]
714    #[test_case(array_def(&[]), bytes(&[]) => Ordering::Less)]
715    // Map <--> ...
716    #[test_case(map_def(&[]), map_def(&[]) => Ordering::Equal)]
717    #[test_case(map_def(&[]), map_indef(&[]) => Ordering::Equal)]
718    #[test_case(map_indef(&[]), map_def(&[]) => Ordering::Equal)]
719    #[test_case(
720        map_def(&[(int(14), int(42))]),
721        map_def(&[(int(14), int(41))])
722        => Ordering::Greater
723    )]
724    #[test_case(
725        map_def(&[(int(14), int(41))]),
726        map_def(&[(int(14), int(42))])
727        => Ordering::Less
728    )]
729    #[test_case(
730        map_def(&[(int(14), int(42))]),
731        map_def(&[(int(14), int(42))])
732        => Ordering::Equal
733    )]
734    #[test_case(
735        map_def(&[(int(14), int(42))]),
736        map_indef(&[(int(14), int(42)), (int(1), int(999))])
737        => Ordering::Less
738    )]
739    #[test_case(
740        map_def(&[(int(15), int(42))]),
741        map_indef(&[(int(14), int(42)), (int(1), int(999))])
742        => Ordering::Greater
743    )]
744    #[test_case(map_def(&[]), constr(121, &[]) => Ordering::Greater)]
745    #[test_case(map_def(&[]), array_def(&[]) => Ordering::Less)]
746    #[test_case(map_def(&[]), array_indef(&[]) => Ordering::Less)]
747    #[test_case(map_def(&[]), int(0) => Ordering::Less)]
748    #[test_case(map_def(&[]), bytes(&[]) => Ordering::Less)]
749    // Constr <-->
750    #[test_case(constr(121, &[]), constr(121, &[]) => Ordering::Equal)]
751    #[test_case(constr(122, &[]), constr(121, &[]) => Ordering::Greater)]
752    #[test_case(constr(122, &[]), constr(121, &[int(999)]) => Ordering::Greater)]
753    #[test_case(constr(126, &[int(999)]), constr(1281, &[]) => Ordering::Less)]
754    #[test_case(constr_any(0, &[]), constr(121, &[]) => Ordering::Equal)]
755    #[test_case(constr_any(1, &[]), constr(121, &[]) => Ordering::Greater)]
756    #[test_case(constr_any(7, &[int(14)]), constr(1280, &[]) => Ordering::Greater)]
757    #[test_case(constr_any(7, &[int(14)]), constr(1281, &[]) => Ordering::Less)]
758    #[test_case(constr_any(121, &[]), map_def(&[]) => Ordering::Less)]
759    #[test_case(constr_any(121, &[]), map_indef(&[]) => Ordering::Less)]
760    #[test_case(constr_any(121, &[]), array_def(&[]) => Ordering::Less)]
761    #[test_case(constr_any(121, &[]), array_indef(&[]) => Ordering::Less)]
762    #[test_case(constr_any(121, &[]), int(0) => Ordering::Less)]
763    #[test_case(constr_any(121, &[]), bytes(&[]) => Ordering::Less)]
764    fn ordering(left: PlutusData, right: PlutusData) -> Ordering {
765        left.cmp(&right)
766    }
767}