• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ergoplatform / sigma-rust / 13381617629

18 Feb 2025 01:49AM UTC coverage: 78.416% (-0.007%) from 78.423%
13381617629

Pull #809

github

web-flow
Merge 72958a0bf into 058b31728
Pull Request #809: This PR focuses on documentation updates. All CI requirements have been validated locally where applicable.

11132 of 14196 relevant lines covered (78.42%)

3.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.45
/ergotree-ir/src/serialization/types.rs
1
use super::op_code::OpCode;
2
use super::sigma_byte_writer::SigmaByteWrite;
3
use super::SigmaSerializationError;
4
use crate::serialization::SigmaSerializeResult;
5
use crate::serialization::{
6
    sigma_byte_reader::SigmaByteRead, SigmaParsingError, SigmaSerializable,
7
};
8
use crate::types::stuple;
9
use crate::types::stype::SType;
10
use crate::types::stype_param;
11
use alloc::string::ToString;
12
use alloc::vec::Vec;
13
use core::convert::TryInto;
14
use num_derive::FromPrimitive;
15
use num_traits::FromPrimitive;
16

17
#[allow(non_camel_case_types)]
18
#[allow(clippy::upper_case_acronyms)] // to differentiate from similarly named SType enum variants
19
#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive)]
20
#[repr(u8)]
21
pub enum TypeCode {
22
    SBOOLEAN = 1,
23
    SBYTE = 2,
24
    SSHORT = 3,
25
    SINT = 4,
26
    SLONG = 5,
27
    SBIGINT = 6,
28
    SGROUP_ELEMENT = 7,
29
    SSIGMAPROP = 8,
30

31
    COLL = (TypeCode::MAX_PRIM_TYPECODE + 1) * TypeCode::COLLECTION_CONSTR_ID, // 12 * 1
32
    COLL_BOOL = TypeCode::COLL as u8 + TypeCode::SBOOLEAN as u8,               // 13
33
    COLL_BYTE = TypeCode::COLL as u8 + TypeCode::SBYTE as u8,                  // 14
34
    COLL_SHORT = TypeCode::COLL as u8 + TypeCode::SSHORT as u8,                // 15
35
    COLL_INT = TypeCode::COLL as u8 + TypeCode::SINT as u8,                    // 16
36
    COLL_LONG = TypeCode::COLL as u8 + TypeCode::SLONG as u8,                  // 17
37
    COLL_BIGINT = TypeCode::COLL as u8 + TypeCode::SBIGINT as u8,              // 18
38
    COLL_GROUP_ELEMENT = TypeCode::COLL as u8 + TypeCode::SGROUP_ELEMENT as u8, // 19
39
    COLL_SIGMAPROP = TypeCode::COLL as u8 + TypeCode::SSIGMAPROP as u8,        // 20
40

41
    NESTED_COLL_BOOL = TypeCode::NESTED_COLL + TypeCode::SBOOLEAN as u8, // 25
42
    NESTED_COLL_BYTE = TypeCode::NESTED_COLL + TypeCode::SBYTE as u8,    // 26
43
    NESTED_COLL_SHORT = TypeCode::NESTED_COLL + TypeCode::SSHORT as u8,  // 27
44
    NESTED_COLL_INT = TypeCode::NESTED_COLL + TypeCode::SINT as u8,      // 28
45
    NESTED_COLL_LONG = TypeCode::NESTED_COLL + TypeCode::SLONG as u8,    // 29
46
    NESTED_COLL_BIGINT = TypeCode::NESTED_COLL + TypeCode::SBIGINT as u8, // 30
47
    NESTED_COLL_GROUP_ELEMENT = TypeCode::NESTED_COLL + TypeCode::SGROUP_ELEMENT as u8, // 31
48
    NESTED_COLL_SIGMAPROP = TypeCode::NESTED_COLL + TypeCode::SSIGMAPROP as u8, // 32
49

50
    OPTION = (TypeCode::MAX_PRIM_TYPECODE + 1) * TypeCode::OPTION_CONSTR_ID, // 12 * 3 = 36
51
    OPTION_BOOL = TypeCode::OPTION as u8 + TypeCode::SBOOLEAN as u8,         // 37
52
    OPTION_BYTE = TypeCode::OPTION as u8 + TypeCode::SBYTE as u8,            // 38
53
    OPTION_SHORT = TypeCode::OPTION as u8 + TypeCode::SSHORT as u8,          // 39
54
    OPTION_INT = TypeCode::OPTION as u8 + TypeCode::SINT as u8,              // 40
55
    OPTION_LONG = TypeCode::OPTION as u8 + TypeCode::SLONG as u8,            // 41
56
    OPTION_BIGINT = TypeCode::OPTION as u8 + TypeCode::SBIGINT as u8,        // 42
57
    OPTION_GROUP_ELEMENT = TypeCode::OPTION as u8 + TypeCode::SGROUP_ELEMENT as u8, // 43
58
    OPTION_SIGMAPROP = TypeCode::OPTION as u8 + TypeCode::SSIGMAPROP as u8,  // 44
59

60
    OPTION_COLL_BOOL = TypeCode::OPTION_COLLECTION + TypeCode::SBOOLEAN as u8, // 49
61
    OPTION_COLL_BYTE = TypeCode::OPTION_COLLECTION + TypeCode::SBYTE as u8,    // 50
62
    OPTION_COLL_SHORT = TypeCode::OPTION_COLLECTION + TypeCode::SSHORT as u8,  // 51
63
    OPTION_COLL_INT = TypeCode::OPTION_COLLECTION + TypeCode::SINT as u8,      // 52
64
    OPTION_COLL_LONG = TypeCode::OPTION_COLLECTION + TypeCode::SLONG as u8,    // 53
65
    OPTION_COLL_BIGINT = TypeCode::OPTION_COLLECTION + TypeCode::SBIGINT as u8, // 54
66
    OPTION_COLL_GROUP_ELEMENT = TypeCode::OPTION_COLLECTION + TypeCode::SGROUP_ELEMENT as u8, // 55
67
    OPTION_COLL_SIGMAPROP = TypeCode::OPTION_COLLECTION + TypeCode::SSIGMAPROP as u8, // 56
68

69
    TUPLE_PAIR1 = (TypeCode::MAX_PRIM_TYPECODE + 1) * TypeCode::TUPLE_PAIR1_CONSTR_ID, // 12 * 5 = 60
70
    TUPLE_PAIR1_BOOL = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SBOOLEAN as u8,         // 61
71
    TUPLE_PAIR1_BYTE = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SBYTE as u8,            // 62
72
    TUPLE_PAIR1_SHORT = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SSHORT as u8,          // 63
73
    TUPLE_PAIR1_INT = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SINT as u8,              // 64
74
    TUPLE_PAIR1_LONG = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SLONG as u8,            // 65
75
    TUPLE_PAIR1_BIGINT = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SBIGINT as u8,        // 66
76
    TUPLE_PAIR1_GROUP_ELEMENT = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SGROUP_ELEMENT as u8, // 67
77
    TUPLE_PAIR1_SIGMAPROP = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SSIGMAPROP as u8,  // 68
78

79
    TUPLE_TRIPLE = Self::TUPLE_PAIR2, // 72
80

81
    TUPLE_PAIR2_BOOL = TypeCode::TUPLE_PAIR2 + TypeCode::SBOOLEAN as u8, // 73
82
    TUPLE_PAIR2_BYTE = TypeCode::TUPLE_PAIR2 + TypeCode::SBYTE as u8,    // 74
83
    TUPLE_PAIR2_SHORT = TypeCode::TUPLE_PAIR2 + TypeCode::SSHORT as u8,  // 75
84
    TUPLE_PAIR2_INT = TypeCode::TUPLE_PAIR2 + TypeCode::SINT as u8,      // 76
85
    TUPLE_PAIR2_LONG = TypeCode::TUPLE_PAIR2 + TypeCode::SLONG as u8,    // 77
86
    TUPLE_PAIR2_BIGINT = TypeCode::TUPLE_PAIR2 + TypeCode::SBIGINT as u8, // 78
87
    TUPLE_PAIR2_GROUP_ELEMENT = TypeCode::TUPLE_PAIR2 + TypeCode::SGROUP_ELEMENT as u8, // 79
88
    TUPLE_PAIR2_SIGMAPROP = TypeCode::TUPLE_PAIR2 + TypeCode::SSIGMAPROP as u8, // 80
89

90
    TUPLE_QUADRUPLE = Self::TUPLE_PAIR_SYMMETRIC, // 84
91

92
    TUPLE_PAIR_SYMMETRIC_BOOL = TypeCode::TUPLE_PAIR_SYMMETRIC + TypeCode::SBOOLEAN as u8, // 85
93
    TUPLE_PAIR_SYMMETRIC_BYTE = TypeCode::TUPLE_PAIR_SYMMETRIC + TypeCode::SBYTE as u8,    // 86
94
    TUPLE_PAIR_SYMMETRIC_SHORT = TypeCode::TUPLE_PAIR_SYMMETRIC + TypeCode::SSHORT as u8,  // 87
95
    TUPLE_PAIR_SYMMETRIC_INT = TypeCode::TUPLE_PAIR_SYMMETRIC + TypeCode::SINT as u8,      // 88
96
    TUPLE_PAIR_SYMMETRIC_LONG = TypeCode::TUPLE_PAIR_SYMMETRIC + TypeCode::SLONG as u8,    // 89
97
    TUPLE_PAIR_SYMMETRIC_BIGINT = TypeCode::TUPLE_PAIR_SYMMETRIC + TypeCode::SBIGINT as u8, // 90
98
    TUPLE_PAIR_SYMMETRIC_GROUP_ELEMENT =
99
        TypeCode::TUPLE_PAIR_SYMMETRIC + TypeCode::SGROUP_ELEMENT as u8, // 91
100
    TUPLE_PAIR_SYMMETRIC_SIGMAPROP = TypeCode::TUPLE_PAIR_SYMMETRIC + TypeCode::SSIGMAPROP as u8, // 92
101

102
    TUPLE = (TypeCode::MAX_PRIM_TYPECODE + 1) * 8, // 12 * 8 = 96
103

104
    SANY = 97,
105
    SUNIT = 98,
106
    SBOX = 99,
107
    SAVL_TREE = 100,
108
    SCONTEXT = 101,
109
    SSTRING = 102,
110
    STYPE_VAR = 103,
111
    SHEADER = 104,
112
    SPRE_HEADER = 105,
113
    SGLOBAL = 106,
114
}
115

116
impl TypeCode {
117
    /// SFunc types occupy remaining space of byte values [FirstFuncType .. 255]
118
    #[allow(dead_code)]
119
    const FIRST_FUNC_TYPE: u8 = OpCode::LAST_DATA_TYPE.value();
120
    #[allow(dead_code)]
121
    const LAST_FUNC_TYPE: u8 = 255;
122

123
    /// Type code of the last valid prim type so that (1 to LastPrimTypeCode) is a range of valid codes.
124
    #[allow(dead_code)]
125
    const LAST_PRIM_TYPECODE: u8 = 8;
126

127
    /// Upper limit of the interval of valid type codes for primitive types
128
    const MAX_PRIM_TYPECODE: u8 = 11;
129

130
    const COLLECTION_CONSTR_ID: u8 = 1;
131

132
    const NESTED_COLLECTION_CONSTS_ID: u8 = 2;
133
    const NESTED_COLL: u8 =
134
        (TypeCode::MAX_PRIM_TYPECODE + 1) * TypeCode::NESTED_COLLECTION_CONSTS_ID; // 12 * 2 = 24
135

136
    const OPTION_CONSTR_ID: u8 = 3;
137
    const OPTION_COLLECTION_TYPE_CONSTR_ID: u8 = 4;
138
    const OPTION_COLLECTION: u8 =
139
        (TypeCode::MAX_PRIM_TYPECODE + 1) * TypeCode::OPTION_COLLECTION_TYPE_CONSTR_ID; // 12 * 4 = 48
140

141
    const TUPLE_PAIR1_CONSTR_ID: u8 = 5;
142

143
    const TUPLE_PAIR2_CONSTR_ID: u8 = 6;
144
    const TUPLE_PAIR2: u8 = (TypeCode::MAX_PRIM_TYPECODE + 1) * TypeCode::TUPLE_PAIR2_CONSTR_ID; // 12 * 6 = 72
145

146
    const TUPLE_PAIR_SYMMETRIC_TYPE_CONSTR_ID: u8 = 7;
147
    const TUPLE_PAIR_SYMMETRIC: u8 =
148
        (TypeCode::MAX_PRIM_TYPECODE + 1) * TypeCode::TUPLE_PAIR_SYMMETRIC_TYPE_CONSTR_ID; // 12 * 7 = 84
149

150
    /// Parse type code from byte
151
    pub(crate) fn parse(b: u8) -> Result<Self, SigmaParsingError> {
6✔
152
        match FromPrimitive::from_u8(b) {
8✔
153
            Some(t) => Ok(t),
6✔
154
            None => Err(SigmaParsingError::InvalidTypeCode(b)),
1✔
155
        }
156
    }
157

158
    pub(crate) const fn value(&self) -> u8 {
7✔
159
        *self as u8
7✔
160
    }
161
}
162

163
impl SigmaSerializable for TypeCode {
164
    fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> SigmaSerializeResult {
7✔
165
        w.put_u8(self.value())?;
7✔
166
        Ok(())
7✔
167
    }
168

169
    fn sigma_parse<R: SigmaByteRead>(r: &mut R) -> Result<Self, SigmaParsingError> {
14✔
170
        let b = r.get_u8()?;
12✔
171
        Self::parse(b)
14✔
172
    }
173
}
174

175
impl SType {
176
    /// Parse type from byte stream. This function should be used instead of
177
    /// `sigma_parse` when type code is already read for look-ahead
178
    pub(crate) fn parse_with_type_code<R: SigmaByteRead>(
12✔
179
        r: &mut R,
180
        c: TypeCode,
181
    ) -> Result<Self, SigmaParsingError> {
182
        use SType::*;
183
        Ok(match c {
28✔
184
            TypeCode::SBOOLEAN => SBoolean,
8✔
185
            TypeCode::SBYTE => SByte,
8✔
186
            TypeCode::SSHORT => SShort,
7✔
187
            TypeCode::SINT => SInt,
11✔
188
            TypeCode::SLONG => SLong,
9✔
189
            TypeCode::SBIGINT => SBigInt,
9✔
190
            TypeCode::SGROUP_ELEMENT => SGroupElement,
8✔
191
            TypeCode::SSIGMAPROP => SSigmaProp,
8✔
192

193
            TypeCode::COLL => SColl(SType::sigma_parse(r)?.into()),
4✔
194
            TypeCode::COLL_BOOL => SColl(SBoolean.into()),
7✔
195
            TypeCode::COLL_BYTE => SColl(SByte.into()),
8✔
196
            TypeCode::COLL_SHORT => SColl(SShort.into()),
7✔
197
            TypeCode::COLL_INT => SColl(SInt.into()),
7✔
198
            TypeCode::COLL_LONG => SColl(SLong.into()),
8✔
199
            TypeCode::COLL_BIGINT => SColl(SBigInt.into()),
7✔
200
            TypeCode::COLL_GROUP_ELEMENT => SColl(SGroupElement.into()),
7✔
201
            TypeCode::COLL_SIGMAPROP => SColl(SSigmaProp.into()),
7✔
202

203
            TypeCode::NESTED_COLL_BOOL => SColl(SColl(SBoolean.into()).into()),
1✔
204
            TypeCode::NESTED_COLL_BYTE => SColl(SColl(SByte.into()).into()),
7✔
205
            TypeCode::NESTED_COLL_SHORT => SColl(SColl(SShort.into()).into()),
×
206
            TypeCode::NESTED_COLL_INT => SColl(SColl(SInt.into()).into()),
1✔
207
            TypeCode::NESTED_COLL_LONG => SColl(SColl(SLong.into()).into()),
1✔
208
            TypeCode::NESTED_COLL_BIGINT => SColl(SColl(SBigInt.into()).into()),
1✔
209
            TypeCode::NESTED_COLL_GROUP_ELEMENT => SColl(SColl(SGroupElement.into()).into()),
×
210
            TypeCode::NESTED_COLL_SIGMAPROP => SColl(SColl(SSigmaProp.into()).into()),
1✔
211

212
            TypeCode::OPTION => SOption(SType::sigma_parse(r)?.into()),
4✔
213
            TypeCode::OPTION_BOOL => SOption(SBoolean.into()),
2✔
214
            TypeCode::OPTION_BYTE => SOption(SByte.into()),
2✔
215
            TypeCode::OPTION_SHORT => SOption(SShort.into()),
2✔
216
            TypeCode::OPTION_INT => SOption(SInt.into()),
2✔
217
            TypeCode::OPTION_LONG => SOption(SLong.into()),
2✔
218
            TypeCode::OPTION_BIGINT => SOption(SBigInt.into()),
2✔
219
            TypeCode::OPTION_GROUP_ELEMENT => SOption(SGroupElement.into()),
2✔
220
            TypeCode::OPTION_SIGMAPROP => SOption(SSigmaProp.into()),
2✔
221

222
            TypeCode::OPTION_COLL_BOOL => SOption(SColl(SBoolean.into()).into()),
×
223
            TypeCode::OPTION_COLL_BYTE => SOption(SColl(SByte.into()).into()),
1✔
224
            TypeCode::OPTION_COLL_SHORT => SOption(SColl(SShort.into()).into()),
×
225
            TypeCode::OPTION_COLL_INT => SOption(SColl(SInt.into()).into()),
×
226
            TypeCode::OPTION_COLL_LONG => SOption(SColl(SLong.into()).into()),
×
227
            TypeCode::OPTION_COLL_BIGINT => SOption(SColl(SBigInt.into()).into()),
×
228
            TypeCode::OPTION_COLL_GROUP_ELEMENT => SOption(SColl(SGroupElement.into()).into()),
1✔
229
            TypeCode::OPTION_COLL_SIGMAPROP => SOption(SColl(SSigmaProp.into()).into()),
×
230

231
            TypeCode::TUPLE_PAIR1 => STuple(stuple::STuple::pair(
10✔
232
                SType::sigma_parse(r)?,
10✔
233
                SType::sigma_parse(r)?,
10✔
234
            )),
235
            TypeCode::TUPLE_PAIR1_BOOL => {
×
236
                STuple(stuple::STuple::pair(SBoolean, SType::sigma_parse(r)?))
7✔
237
            }
238
            TypeCode::TUPLE_PAIR1_BYTE => {
×
239
                STuple(stuple::STuple::pair(SByte, SType::sigma_parse(r)?))
7✔
240
            }
241
            TypeCode::TUPLE_PAIR1_SHORT => {
×
242
                STuple(stuple::STuple::pair(SShort, SType::sigma_parse(r)?))
7✔
243
            }
244
            TypeCode::TUPLE_PAIR1_INT => STuple(stuple::STuple::pair(SInt, SType::sigma_parse(r)?)),
7✔
245
            TypeCode::TUPLE_PAIR1_LONG => {
×
246
                STuple(stuple::STuple::pair(SLong, SType::sigma_parse(r)?))
8✔
247
            }
248
            TypeCode::TUPLE_PAIR1_BIGINT => {
×
249
                STuple(stuple::STuple::pair(SBigInt, SType::sigma_parse(r)?))
7✔
250
            }
251
            TypeCode::TUPLE_PAIR1_GROUP_ELEMENT => {
×
252
                STuple(stuple::STuple::pair(SGroupElement, SType::sigma_parse(r)?))
6✔
253
            }
254
            TypeCode::TUPLE_PAIR1_SIGMAPROP => {
×
255
                STuple(stuple::STuple::pair(SSigmaProp, SType::sigma_parse(r)?))
6✔
256
            }
257

258
            TypeCode::TUPLE_TRIPLE => STuple(stuple::STuple::triple(
14✔
259
                SType::sigma_parse(r)?,
14✔
260
                SType::sigma_parse(r)?,
14✔
261
                SType::sigma_parse(r)?,
14✔
262
            )),
263

264
            TypeCode::TUPLE_PAIR2_BOOL => {
×
265
                STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SBoolean))
8✔
266
            }
267
            TypeCode::TUPLE_PAIR2_BYTE => {
×
268
                STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SByte))
10✔
269
            }
270
            TypeCode::TUPLE_PAIR2_SHORT => {
×
271
                STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SShort))
6✔
272
            }
273
            TypeCode::TUPLE_PAIR2_INT => STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SInt)),
8✔
274
            TypeCode::TUPLE_PAIR2_LONG => {
×
275
                STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SLong))
10✔
276
            }
277
            TypeCode::TUPLE_PAIR2_BIGINT => {
×
278
                STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SBigInt))
6✔
279
            }
280
            TypeCode::TUPLE_PAIR2_GROUP_ELEMENT => {
×
281
                STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SGroupElement))
8✔
282
            }
283
            TypeCode::TUPLE_PAIR2_SIGMAPROP => {
×
284
                STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SSigmaProp))
8✔
285
            }
286

287
            TypeCode::TUPLE_QUADRUPLE => STuple(stuple::STuple::quadruple(
14✔
288
                SType::sigma_parse(r)?,
14✔
289
                SType::sigma_parse(r)?,
14✔
290
                SType::sigma_parse(r)?,
14✔
291
                SType::sigma_parse(r)?,
14✔
292
            )),
293

294
            TypeCode::TUPLE_PAIR_SYMMETRIC_BOOL => STuple(stuple::STuple::pair(SBoolean, SBoolean)),
4✔
295
            TypeCode::TUPLE_PAIR_SYMMETRIC_BYTE => STuple(stuple::STuple::pair(SByte, SByte)),
3✔
296
            TypeCode::TUPLE_PAIR_SYMMETRIC_SHORT => STuple(stuple::STuple::pair(SShort, SShort)),
×
297
            TypeCode::TUPLE_PAIR_SYMMETRIC_INT => STuple(stuple::STuple::pair(SInt, SInt)),
6✔
298
            TypeCode::TUPLE_PAIR_SYMMETRIC_LONG => STuple(stuple::STuple::pair(SLong, SLong)),
6✔
299
            TypeCode::TUPLE_PAIR_SYMMETRIC_BIGINT => STuple(stuple::STuple::pair(SBigInt, SBigInt)),
4✔
300
            TypeCode::TUPLE_PAIR_SYMMETRIC_GROUP_ELEMENT => {
×
301
                STuple(stuple::STuple::pair(SGroupElement, SGroupElement))
4✔
302
            }
303
            TypeCode::TUPLE_PAIR_SYMMETRIC_SIGMAPROP => {
×
304
                STuple(stuple::STuple::pair(SSigmaProp, SSigmaProp))
5✔
305
            }
306

307
            TypeCode::TUPLE => {
×
308
                let len = r.get_u8()?;
4✔
309
                let mut items = Vec::with_capacity(len as usize);
2✔
310
                for _ in 0..len {
4✔
311
                    items.push(SType::sigma_parse(r)?);
4✔
312
                }
313
                SType::STuple(
2✔
314
                    items
4✔
315
                        .try_into()
×
316
                        .map_err(|_| SigmaParsingError::TupleItemsOutOfBounds(len as usize))?,
×
317
                )
318
            }
319

320
            TypeCode::SANY => SAny,
2✔
321
            TypeCode::SUNIT => SUnit,
1✔
322
            TypeCode::SBOX => SBox,
4✔
323
            TypeCode::SAVL_TREE => SAvlTree,
2✔
324
            TypeCode::SCONTEXT => SContext,
2✔
325
            TypeCode::SSTRING => SString,
2✔
326
            TypeCode::STYPE_VAR => STypeVar(stype_param::STypeVar::sigma_parse(r)?),
4✔
327
            TypeCode::SHEADER => SHeader,
2✔
328
            TypeCode::SPRE_HEADER => SPreHeader,
2✔
329
            TypeCode::SGLOBAL => SGlobal,
2✔
330
        })
331
    }
332
}
333

334
/// Each SType is serialized to array of bytes by:
335
/// - emitting typeCode of each node (see special case for collections below)
336
/// - then recursively serializing subtrees from left to right on each level
337
/// - for each collection of primitive type there is special type code to emit single byte instead of two bytes
338
///
339
/// Types code intervals
340
/// - (1 .. MaxPrimTypeCode)  // primitive types
341
/// - (CollectionTypeCode .. CollectionTypeCode + MaxPrimTypeCode) // collections of primitive types
342
/// - (MaxCollectionTypeCode ..)  // Other types
343
///
344
/// Collection of non-primitive type is serialized as (CollectionTypeCode, serialize(elementType))
345
impl SigmaSerializable for SType {
346
    fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> SigmaSerializeResult {
8✔
347
        // for reference see http://github.com/ScorexFoundation/sigmastate-interpreter/blob/25251c1313b0131835f92099f02cef8a5d932b5e/sigmastate/src/main/scala/sigmastate/serialization/TypeSerializer.scala#L25-L25
348
        use SType::*;
349
        match self {
8✔
350
            SType::SFunc(_) => Err(SigmaSerializationError::NotSupported(
×
351
                "SFunc serialization is no supported".to_string(),
×
352
            )),
353
            SType::SAny => TypeCode::SANY.sigma_serialize(w),
1✔
354
            SType::SUnit => TypeCode::SUNIT.sigma_serialize(w),
×
355
            SType::SBoolean => TypeCode::SBOOLEAN.sigma_serialize(w),
5✔
356
            SType::SByte => TypeCode::SBYTE.sigma_serialize(w),
5✔
357
            SType::SShort => TypeCode::SSHORT.sigma_serialize(w),
5✔
358
            SType::SInt => TypeCode::SINT.sigma_serialize(w),
6✔
359
            SType::SLong => TypeCode::SLONG.sigma_serialize(w),
7✔
360
            SType::SBigInt => TypeCode::SBIGINT.sigma_serialize(w),
9✔
361
            SType::SGroupElement => TypeCode::SGROUP_ELEMENT.sigma_serialize(w),
5✔
362
            SType::SSigmaProp => TypeCode::SSIGMAPROP.sigma_serialize(w),
5✔
363
            SType::SBox => TypeCode::SBOX.sigma_serialize(w),
2✔
364
            SType::SAvlTree => TypeCode::SAVL_TREE.sigma_serialize(w),
1✔
365
            SType::SContext => TypeCode::SCONTEXT.sigma_serialize(w),
1✔
366
            SType::SString => TypeCode::SSTRING.sigma_serialize(w),
1✔
367
            SType::SHeader => TypeCode::SHEADER.sigma_serialize(w),
1✔
368
            SType::SPreHeader => TypeCode::SPRE_HEADER.sigma_serialize(w),
1✔
369
            SType::SGlobal => TypeCode::SGLOBAL.sigma_serialize(w),
1✔
370
            SOption(elem_type) => match &**elem_type {
1✔
371
                SBoolean => TypeCode::OPTION_BOOL.sigma_serialize(w),
1✔
372
                SByte => TypeCode::OPTION_BYTE.sigma_serialize(w),
1✔
373
                SShort => TypeCode::OPTION_SHORT.sigma_serialize(w),
1✔
374
                SInt => TypeCode::OPTION_INT.sigma_serialize(w),
1✔
375
                SLong => TypeCode::OPTION_LONG.sigma_serialize(w),
1✔
376
                SBigInt => TypeCode::OPTION_BIGINT.sigma_serialize(w),
1✔
377
                SGroupElement => TypeCode::OPTION_GROUP_ELEMENT.sigma_serialize(w),
1✔
378
                SSigmaProp => TypeCode::OPTION_SIGMAPROP.sigma_serialize(w),
1✔
379
                SColl(inner_elem_type) => match &**inner_elem_type {
1✔
380
                    SBoolean => TypeCode::OPTION_COLL_BOOL.sigma_serialize(w),
×
381
                    SByte => TypeCode::OPTION_COLL_BYTE.sigma_serialize(w),
×
382
                    SShort => TypeCode::OPTION_COLL_SHORT.sigma_serialize(w),
×
383
                    SInt => TypeCode::OPTION_COLL_INT.sigma_serialize(w),
×
384
                    SLong => TypeCode::OPTION_COLL_LONG.sigma_serialize(w),
×
385
                    SBigInt => TypeCode::OPTION_COLL_BIGINT.sigma_serialize(w),
×
386
                    SGroupElement => TypeCode::OPTION_COLL_GROUP_ELEMENT.sigma_serialize(w),
1✔
387
                    SSigmaProp => TypeCode::OPTION_COLL_SIGMAPROP.sigma_serialize(w),
×
388
                    STypeVar(_) | SAny | SUnit | SBox | SAvlTree | SOption(_) | SColl(_)
×
389
                    | STuple(_) | SFunc(_) | SContext | SString | SHeader | SPreHeader
×
390
                    | SGlobal => {
×
391
                        // if not "embeddable" type fallback to generic Option type code following
392
                        // elem type code
393
                        TypeCode::OPTION.sigma_serialize(w)?;
1✔
394
                        elem_type.sigma_serialize(w)
1✔
395
                    }
396
                },
397
                STypeVar(_) | SAny | SUnit | SBox | SAvlTree | SOption(_) | STuple(_)
×
398
                | SFunc(_) | SContext | SString | SHeader | SPreHeader | SGlobal => {
×
399
                    // if not "embeddable" type fallback to generic Option type code following
400
                    // elem type code
401
                    TypeCode::OPTION.sigma_serialize(w)?;
1✔
402
                    elem_type.sigma_serialize(w)
1✔
403
                }
404
            },
405

406
            SType::SColl(elem_type) => match &**elem_type {
6✔
407
                SBoolean => TypeCode::COLL_BOOL.sigma_serialize(w),
5✔
408
                SByte => TypeCode::COLL_BYTE.sigma_serialize(w),
5✔
409
                SShort => TypeCode::COLL_SHORT.sigma_serialize(w),
5✔
410
                SInt => TypeCode::COLL_INT.sigma_serialize(w),
5✔
411
                SLong => TypeCode::COLL_LONG.sigma_serialize(w),
5✔
412
                SBigInt => TypeCode::COLL_BIGINT.sigma_serialize(w),
5✔
413
                SGroupElement => TypeCode::COLL_GROUP_ELEMENT.sigma_serialize(w),
5✔
414
                SSigmaProp => TypeCode::COLL_SIGMAPROP.sigma_serialize(w),
5✔
415
                SColl(inner_elem_type) => match &**inner_elem_type {
5✔
416
                    SBoolean => TypeCode::NESTED_COLL_BOOL.sigma_serialize(w),
1✔
417
                    SByte => TypeCode::NESTED_COLL_BYTE.sigma_serialize(w),
5✔
418
                    SShort => TypeCode::NESTED_COLL_SHORT.sigma_serialize(w),
×
419
                    SInt => TypeCode::NESTED_COLL_INT.sigma_serialize(w),
1✔
420
                    SLong => TypeCode::NESTED_COLL_LONG.sigma_serialize(w),
1✔
421
                    SBigInt => TypeCode::NESTED_COLL_BIGINT.sigma_serialize(w),
1✔
422
                    SGroupElement => TypeCode::NESTED_COLL_GROUP_ELEMENT.sigma_serialize(w),
×
423
                    SSigmaProp => TypeCode::NESTED_COLL_SIGMAPROP.sigma_serialize(w),
1✔
424
                    STypeVar(_) | SAny | SUnit | SBox | SAvlTree | SOption(_) | SColl(_)
×
425
                    | STuple(_) | SFunc(_) | SContext | SString | SHeader | SPreHeader
×
426
                    | SGlobal => {
×
427
                        // if not "embeddable" type fallback to generic Coll type code following
428
                        // elem type code
429
                        TypeCode::COLL.sigma_serialize(w)?;
1✔
430
                        elem_type.sigma_serialize(w)
1✔
431
                    }
432
                },
433
                STypeVar(_) | SAny | SUnit | SBox | SAvlTree | SOption(_) | STuple(_)
×
434
                | SFunc(_) | SContext | SString | SHeader | SPreHeader | SGlobal => {
×
435
                    // if not "embeddable" type fallback to generic Coll type code following
436
                    // elem type code
437
                    TypeCode::COLL.sigma_serialize(w)?;
1✔
438
                    elem_type.sigma_serialize(w)
1✔
439
                }
440
            },
441
            SType::STuple(stuple::STuple { items }) => match items.clone().as_slice() {
5✔
442
                [t1, t2] => match (t1, t2) {
19✔
443
                    (SBoolean, SBoolean) => TypeCode::TUPLE_PAIR_SYMMETRIC_BOOL.sigma_serialize(w),
8✔
444
                    (SByte, SByte) => TypeCode::TUPLE_PAIR_SYMMETRIC_BYTE.sigma_serialize(w),
6✔
445
                    (SInt, SInt) => TypeCode::TUPLE_PAIR_SYMMETRIC_INT.sigma_serialize(w),
8✔
446
                    (SLong, SLong) => TypeCode::TUPLE_PAIR_SYMMETRIC_LONG.sigma_serialize(w),
8✔
447
                    (SBigInt, SBigInt) => TypeCode::TUPLE_PAIR_SYMMETRIC_BIGINT.sigma_serialize(w),
8✔
448
                    (SGroupElement, SGroupElement) => {
×
449
                        TypeCode::TUPLE_PAIR_SYMMETRIC_GROUP_ELEMENT.sigma_serialize(w)
6✔
450
                    }
451
                    (SSigmaProp, SSigmaProp) => {
×
452
                        TypeCode::TUPLE_PAIR_SYMMETRIC_SIGMAPROP.sigma_serialize(w)
8✔
453
                    }
454

455
                    (SBoolean, t2) => {
5✔
456
                        TypeCode::TUPLE_PAIR1_BOOL.sigma_serialize(w)?;
10✔
457
                        t2.sigma_serialize(w)
10✔
458
                    }
459
                    (SByte, t2) => {
4✔
460
                        TypeCode::TUPLE_PAIR1_BYTE.sigma_serialize(w)?;
8✔
461
                        t2.sigma_serialize(w)
8✔
462
                    }
463
                    (SShort, t2) => {
5✔
464
                        TypeCode::TUPLE_PAIR1_SHORT.sigma_serialize(w)?;
11✔
465
                        t2.sigma_serialize(w)
10✔
466
                    }
467
                    (SInt, t2) => {
4✔
468
                        TypeCode::TUPLE_PAIR1_INT.sigma_serialize(w)?;
8✔
469
                        t2.sigma_serialize(w)
8✔
470
                    }
471
                    (SLong, t2) => {
5✔
472
                        TypeCode::TUPLE_PAIR1_LONG.sigma_serialize(w)?;
10✔
473
                        t2.sigma_serialize(w)
10✔
474
                    }
475
                    (SBigInt, t2) => {
4✔
476
                        TypeCode::TUPLE_PAIR1_BIGINT.sigma_serialize(w)?;
8✔
477
                        t2.sigma_serialize(w)
9✔
478
                    }
479
                    (SGroupElement, t2) => {
4✔
480
                        TypeCode::TUPLE_PAIR1_GROUP_ELEMENT.sigma_serialize(w)?;
8✔
481
                        t2.sigma_serialize(w)
8✔
482
                    }
483
                    (SSigmaProp, t2) => {
5✔
484
                        TypeCode::TUPLE_PAIR1_SIGMAPROP.sigma_serialize(w)?;
10✔
485
                        t2.sigma_serialize(w)
10✔
486
                    }
487

488
                    (t1, SBoolean) => {
3✔
489
                        TypeCode::TUPLE_PAIR2_BOOL.sigma_serialize(w)?;
6✔
490
                        t1.sigma_serialize(w)
6✔
491
                    }
492
                    (t1, SByte) => {
4✔
493
                        TypeCode::TUPLE_PAIR2_BYTE.sigma_serialize(w)?;
8✔
494
                        t1.sigma_serialize(w)
8✔
495
                    }
496
                    (t1, SShort) => {
3✔
497
                        TypeCode::TUPLE_PAIR2_SHORT.sigma_serialize(w)?;
6✔
498
                        t1.sigma_serialize(w)
6✔
499
                    }
500
                    (t1, SInt) => {
3✔
501
                        TypeCode::TUPLE_PAIR2_INT.sigma_serialize(w)?;
6✔
502
                        t1.sigma_serialize(w)
6✔
503
                    }
504
                    (t1, SLong) => {
4✔
505
                        TypeCode::TUPLE_PAIR2_LONG.sigma_serialize(w)?;
8✔
506
                        t1.sigma_serialize(w)
8✔
507
                    }
508
                    (t1, SBigInt) => {
3✔
509
                        TypeCode::TUPLE_PAIR2_BIGINT.sigma_serialize(w)?;
6✔
510
                        t1.sigma_serialize(w)
6✔
511
                    }
512
                    (t1, SGroupElement) => {
4✔
513
                        TypeCode::TUPLE_PAIR2_GROUP_ELEMENT.sigma_serialize(w)?;
8✔
514
                        t1.sigma_serialize(w)
8✔
515
                    }
516
                    (t1, SSigmaProp) => {
3✔
517
                        TypeCode::TUPLE_PAIR2_SIGMAPROP.sigma_serialize(w)?;
6✔
518
                        t1.sigma_serialize(w)
6✔
519
                    }
520
                    (
521
                        STypeVar(_) | SAny | SUnit | SBox | SAvlTree | SOption(_) | SColl(_)
×
522
                        | STuple(_) | SFunc(_) | SContext | SString | SHeader | SPreHeader
×
523
                        | SGlobal,
×
524
                        STypeVar(_) | SAny | SUnit | SBox | SAvlTree | SOption(_) | SColl(_)
×
525
                        | STuple(_) | SFunc(_) | SContext | SString | SHeader | SPreHeader
×
526
                        | SGlobal,
×
527
                    ) => {
×
528
                        // Pair of non-primitive types (`(SBox, SAvlTree)`, `((Int, Byte), (Boolean,Box))`, etc.)
529
                        TypeCode::TUPLE_PAIR1.sigma_serialize(w)?;
3✔
530
                        t1.sigma_serialize(w)?;
6✔
531
                        t2.sigma_serialize(w)
6✔
532
                    }
533
                },
534
                [t1, t2, t3] => {
10✔
535
                    TypeCode::TUPLE_TRIPLE.sigma_serialize(w)?;
10✔
536
                    t1.sigma_serialize(w)?;
10✔
537
                    t2.sigma_serialize(w)?;
10✔
538
                    t3.sigma_serialize(w)
10✔
539
                }
540
                [t1, t2, t3, t4] => {
10✔
541
                    TypeCode::TUPLE_QUADRUPLE.sigma_serialize(w)?;
10✔
542
                    t1.sigma_serialize(w)?;
10✔
543
                    t2.sigma_serialize(w)?;
10✔
544
                    t3.sigma_serialize(w)?;
10✔
545
                    t4.sigma_serialize(w)
10✔
546
                }
547
                _ => {
×
548
                    TypeCode::TUPLE.sigma_serialize(w)?;
2✔
549
                    w.put_u8(items.len() as u8)?;
2✔
550
                    items.iter().try_for_each(|i| i.sigma_serialize(w))
4✔
551
                }
552
            },
553

554
            SType::STypeVar(tv) => {
1✔
555
                TypeCode::STYPE_VAR.sigma_serialize(w)?;
7✔
556
                tv.sigma_serialize(w)
1✔
557
            }
558
        }
559
    }
560

561
    fn sigma_parse<R: SigmaByteRead>(r: &mut R) -> Result<Self, SigmaParsingError> {
10✔
562
        // for reference see http://github.com/ScorexFoundation/sigmastate-interpreter/blob/25251c1313b0131835f92099f02cef8a5d932b5e/sigmastate/src/main/scala/sigmastate/serialization/TypeSerializer.scala#L118-L118
563
        let c = TypeCode::sigma_parse(r)?;
10✔
564
        Self::parse_with_type_code(r, c)
10✔
565
    }
566
}
567

568
#[cfg(test)]
569
#[cfg(feature = "arbitrary")]
570
#[allow(clippy::panic)]
571
mod tests {
572
    use super::*;
573
    use crate::serialization::sigma_serialize_roundtrip;
574

575
    use proptest::prelude::*;
576

577
    proptest! {
578

579
        #[test]
580
        fn ser_roundtrip(v in any::<SType>()) {
581
            prop_assert_eq![sigma_serialize_roundtrip(&v), v];
582
        }
583
    }
584
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc