plutus_ledger_api/csl/
pla_to_csl.rs

1use cardano_serialization_lib as csl;
2use num_bigint::{BigInt, TryFromBigIntError};
3use num_traits::sign::Signed;
4
5#[derive(Debug, thiserror::Error)]
6pub enum TryFromPLAError {
7    #[error("{0}")]
8    CSLDeserializeError(csl::DeserializeError),
9
10    #[error("{0}")]
11    CSLJsError(csl::JsError),
12
13    #[error("Unable to cast BigInt {0} into type {1}: value is out of bound")]
14    BigIntOutOfRange(BigInt, String),
15
16    #[error("Unable to represent PLA value in CSL: ${0}")]
17    ImpossibleConversion(String),
18
19    #[error("Invalid valid transaction time range: ${0:?}")]
20    InvalidTimeRange(crate::v2::transaction::POSIXTimeRange),
21
22    #[error("Script is missing from context: {0:?}")]
23    MissingScript(crate::v2::script::ScriptHash),
24}
25
26/// Convert a plutus-ledger-api type to its cardano-serialization-lib counterpart
27/// `try_to_csl_with` accepts extra data where the PLA data itself is not enough
28pub trait TryFromPLA<T> {
29    fn try_from_pla(val: &T) -> Result<Self, TryFromPLAError>
30    where
31        Self: Sized;
32}
33
34/// Convert a plutus-ledger-api type to its cardano-serialization-lib counterpart
35/// `try_to_csl_with` accepts extra data where the PLA data itself is not enough
36///
37/// DO NOT IMPLEMENT THIS DIRECTLY. Implement `TryFromPLA` instead.
38pub trait TryToCSL<T> {
39    fn try_to_csl(&self) -> Result<T, TryFromPLAError>;
40}
41
42impl<T, U> TryToCSL<U> for T
43where
44    U: TryFromPLA<T>,
45{
46    fn try_to_csl(&self) -> Result<U, TryFromPLAError> {
47        TryFromPLA::try_from_pla(self)
48    }
49}
50
51impl TryFromPLA<u64> for csl::BigNum {
52    fn try_from_pla(val: &u64) -> Result<Self, TryFromPLAError> {
53        // BigNum(s) are u64 under the hood.
54
55        Ok(csl::BigNum::from(*val))
56    }
57}
58
59impl TryFromPLA<BigInt> for csl::BigNum {
60    fn try_from_pla(val: &BigInt) -> Result<Self, TryFromPLAError> {
61        // BigNum(s) are u64 under the hood.
62        let x: u64 = val
63            .to_owned()
64            .try_into()
65            .map_err(|err: TryFromBigIntError<BigInt>| {
66                TryFromPLAError::BigIntOutOfRange(err.into_original(), "u64".into())
67            })?;
68
69        x.try_to_csl()
70    }
71}
72
73impl TryFromPLA<BigInt> for csl::BigInt {
74    fn try_from_pla(val: &BigInt) -> Result<Self, TryFromPLAError> {
75        Ok(val.to_owned().into())
76    }
77}
78
79impl TryFromPLA<BigInt> for csl::Int {
80    fn try_from_pla(val: &BigInt) -> Result<Self, TryFromPLAError> {
81        if val.is_negative() {
82            Ok(csl::Int::new_negative(&(val.abs()).try_to_csl()?))
83        } else {
84            Ok(csl::Int::new(&val.try_to_csl()?))
85        }
86    }
87}
88
89impl TryFromPLA<i64> for csl::Int {
90    fn try_from_pla(val: &i64) -> Result<Self, TryFromPLAError> {
91        if val.is_negative() {
92            Ok(csl::Int::new_negative(&csl::BigNum::from(
93                val.unsigned_abs(),
94            )))
95        } else {
96            Ok(csl::Int::new(&csl::BigNum::from(*val as u64)))
97        }
98    }
99}
100
101impl TryFromPLA<BigInt> for u32 /* TransactionIndex */ {
102    fn try_from_pla(val: &BigInt) -> Result<Self, TryFromPLAError> {
103        val.to_owned()
104            .try_into()
105            .map_err(|err: TryFromBigIntError<BigInt>| {
106                TryFromPLAError::BigIntOutOfRange(err.into_original(), "u32".into())
107            })
108    }
109}