1use core::marker::PhantomData;
13
14use codec::{Decode, Encode};
15use scale_decode::{DecodeAsType, IntoVisitor, TypeResolver, Visitor, visitor::DecodeAsTypeResult};
16
17use super::{Encoded, Static};
18use alloc::vec::Vec;
19
20#[derive(Clone, Debug, Eq, PartialEq, Encode)]
22pub struct UncheckedExtrinsic<Address, Call, Signature, Extra>(
23 Static<Encoded>,
24 #[codec(skip)] PhantomData<(Address, Call, Signature, Extra)>,
25);
26
27impl<Address, Call, Signature, Extra> UncheckedExtrinsic<Address, Call, Signature, Extra> {
28 pub fn new(bytes: Vec<u8>) -> Self {
30 Self(Static(Encoded(bytes)), PhantomData)
31 }
32
33 pub fn bytes(&self) -> &[u8] {
35 self.0.0.0.as_slice()
36 }
37}
38
39impl<Address, Call, Signature, Extra> Decode
40 for UncheckedExtrinsic<Address, Call, Signature, Extra>
41{
42 fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
43 let xt_vec: Vec<u8> = Decode::decode(input)?;
49 Ok(UncheckedExtrinsic::new(xt_vec))
50 }
51}
52
53impl<Address, Call, Signature, Extra> scale_encode::EncodeAsType
54 for UncheckedExtrinsic<Address, Call, Signature, Extra>
55{
56 fn encode_as_type_to<R: TypeResolver>(
57 &self,
58 type_id: R::TypeId,
59 types: &R,
60 out: &mut Vec<u8>,
61 ) -> Result<(), scale_encode::Error> {
62 self.0.encode_as_type_to(type_id, types, out)
63 }
64}
65
66impl<Address, Call, Signature, Extra> From<Vec<u8>>
67 for UncheckedExtrinsic<Address, Call, Signature, Extra>
68{
69 fn from(bytes: Vec<u8>) -> Self {
70 UncheckedExtrinsic::new(bytes)
71 }
72}
73
74impl<Address, Call, Signature, Extra> From<UncheckedExtrinsic<Address, Call, Signature, Extra>>
75 for Vec<u8>
76{
77 fn from(bytes: UncheckedExtrinsic<Address, Call, Signature, Extra>) -> Self {
78 bytes.0.0.0
79 }
80}
81
82pub struct UncheckedExtrinsicDecodeAsTypeVisitor<Address, Call, Signature, Extra, R: TypeResolver>(
83 PhantomData<(Address, Call, Signature, Extra, R)>,
84);
85
86impl<Address, Call, Signature, Extra, R: TypeResolver> Visitor
87 for UncheckedExtrinsicDecodeAsTypeVisitor<Address, Call, Signature, Extra, R>
88{
89 type Value<'scale, 'info> = UncheckedExtrinsic<Address, Call, Signature, Extra>;
90 type Error = scale_decode::Error;
91 type TypeResolver = R;
92
93 fn unchecked_decode_as_type<'scale, 'info>(
94 self,
95 input: &mut &'scale [u8],
96 type_id: R::TypeId,
97 types: &'info R,
98 ) -> DecodeAsTypeResult<Self, Result<Self::Value<'scale, 'info>, Self::Error>> {
99 DecodeAsTypeResult::Decoded(Self::Value::decode_as_type(input, type_id, types))
100 }
101}
102
103impl<Address, Call, Signature, Extra> IntoVisitor
104 for UncheckedExtrinsic<Address, Call, Signature, Extra>
105{
106 type AnyVisitor<R: TypeResolver> =
107 UncheckedExtrinsicDecodeAsTypeVisitor<Address, Call, Signature, Extra, R>;
108
109 fn into_visitor<R: TypeResolver>()
110 -> UncheckedExtrinsicDecodeAsTypeVisitor<Address, Call, Signature, Extra, R> {
111 UncheckedExtrinsicDecodeAsTypeVisitor(PhantomData)
112 }
113}
114
115#[cfg(test)]
116pub mod tests {
117 use super::*;
118
119 use alloc::vec;
120
121 #[test]
122 fn unchecked_extrinsic_encoding() {
123 let tx_bytes = vec![1u8, 2, 3].encode();
125
126 let unchecked_extrinsic = UncheckedExtrinsic::<(), (), (), ()>::new(tx_bytes.clone());
127 let encoded_tx_bytes = unchecked_extrinsic.encode();
128
129 assert_eq!(tx_bytes, encoded_tx_bytes);
131
132 let decoded_tx = UncheckedExtrinsic::<(), (), (), ()>::decode(&mut &tx_bytes[..]).unwrap();
135 let decoded_tx_bytes = decoded_tx.bytes();
136 let encoded_tx_bytes = decoded_tx.encode();
137
138 assert_eq!(decoded_tx_bytes, encoded_tx_bytes);
139 assert_eq!(vec![1, 2, 3], encoded_tx_bytes);
141 }
142}