thruput_u256/integration.rs
1//! XDR serialization and contract-spec integration.
2//!
3//! Wire format is eight `u32` limbs **most significant first**, matching the
4//! `(high, low)` convention xdrs uses for `u128` -- so the encoded form is the
5//! value as 32 big-endian bytes, the reverse of the in-memory order. [`I256`]
6//! rides the same encoding over its two's complement bits, which is what
7//! Ethereum's `int256` uses and what any non-Rust SDK would guess.
8//!
9//! `CollectAuthHandles`, `ReceiveAuthHandles` and `MintableType` are owned by
10//! `thruput-sdk` and implemented there, for this type.
11
12use crate::{I256, U256};
13use thruput_contract_spec as spec;
14use xdrs::{
15 ReadResult, ReadXDR, Reader, WriteResult, WriteXDR, Writer,
16 WriterUnchecked,
17};
18
19// ---------------------------------------------------------------------------
20// XDR
21// ---------------------------------------------------------------------------
22
23// Eight `u32` limbs most-significant-first is byte-for-byte a fixed opaque of
24// 32 big-endian bytes, which is what `to_be_bytes` already produces -- and
25// what xdrs encodes a `[u8; 32]` as. So these delegate rather than looping
26// over limbs in reverse. `#[derive(ReadXDR, WriteXDR)]` cannot express it:
27// it walks fields in declaration order, and the in-memory order is the
28// opposite one.
29impl<'r> ReadXDR<'r> for U256 {
30 #[inline]
31 fn read_xdr<R: Reader<'r>>(r: &mut R) -> ReadResult<Self> {
32 Ok(Self::from_be_bytes(<[u8; 32] as ReadXDR>::read_xdr(r)?))
33 }
34}
35
36impl WriteXDR for U256 {
37 #[inline]
38 fn write_xdr<F, W: Writer<F>>(&self, w: &mut W) -> WriteResult<()> {
39 self.to_be_bytes().write_xdr(w)
40 }
41
42 #[inline]
43 unsafe fn write_xdr_unchecked<F, W: WriterUnchecked<F>>(&self, w: &mut W) {
44 // SAFETY: caller guarantees space for 32 bytes; a fixed opaque has no
45 // XDR bounds to violate.
46 unsafe { self.to_be_bytes().write_xdr_unchecked(w) }
47 }
48}
49
50impl<'r> ReadXDR<'r> for I256 {
51 #[inline]
52 fn read_xdr<R: Reader<'r>>(r: &mut R) -> ReadResult<Self> {
53 Ok(Self::from_be_bytes(<[u8; 32] as ReadXDR>::read_xdr(r)?))
54 }
55}
56
57impl WriteXDR for I256 {
58 #[inline]
59 fn write_xdr<F, W: Writer<F>>(&self, w: &mut W) -> WriteResult<()> {
60 self.to_be_bytes().write_xdr(w)
61 }
62
63 #[inline]
64 unsafe fn write_xdr_unchecked<F, W: WriterUnchecked<F>>(&self, w: &mut W) {
65 // SAFETY: as above.
66 unsafe { self.to_be_bytes().write_xdr_unchecked(w) }
67 }
68}
69
70// ---------------------------------------------------------------------------
71// Contract spec
72// ---------------------------------------------------------------------------
73
74impl spec::ContractTypeRefSpec for U256 {
75 const INFO: spec::ContractTypeInfo<'static> = spec::ContractTypeInfo {
76 ty: spec::ContractTypeView::U256,
77 };
78}
79
80impl spec::ContractTypeRefSpec for I256 {
81 const INFO: spec::ContractTypeInfo<'static> = spec::ContractTypeInfo {
82 ty: spec::ContractTypeView::I256,
83 };
84}