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

ergoplatform / sigma-rust / 13536308501

26 Feb 2025 04:06AM UTC coverage: 78.501% (+0.08%) from 78.423%
13536308501

Pull #810

github

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

11144 of 14196 relevant lines covered (78.5%)

3.09 hits per line

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

63.99
/ergotree-ir/src/mir/constant.rs
1
//! Constant(Literal) IR node
2

3
use crate::base16_str::Base16Str;
4
use crate::bigint256::BigInt256;
5
use crate::chain::ergo_box::ErgoBox;
6
use crate::chain::token::TokenId;
7
use crate::mir::value::CollKind;
8
use crate::reference::Ref;
9
use crate::serialization::SigmaParsingError;
10
use crate::serialization::SigmaSerializable;
11
use crate::serialization::SigmaSerializationError;
12
use crate::sigma_protocol::sigma_boolean::SigmaBoolean;
13
use crate::sigma_protocol::sigma_boolean::SigmaProofOfKnowledgeTree;
14
use crate::sigma_protocol::sigma_boolean::SigmaProp;
15
use crate::sigma_protocol::sigma_boolean::{ProveDhTuple, ProveDlog};
16
use crate::types::stuple::STuple;
17
use crate::types::stuple::TupleItems;
18
use crate::types::stype::LiftIntoSType;
19
use crate::types::stype::SType;
20
use alloc::boxed::Box;
21

22
use alloc::string::String;
23
use alloc::string::ToString;
24
use alloc::sync::Arc;
25
use alloc::vec::Vec;
26
use core::convert::TryFrom;
27
use core::convert::TryInto;
28
use core::fmt::Formatter;
29
use ergo_chain_types::ADDigest;
30
use ergo_chain_types::Base16DecodedBytes;
31
use ergo_chain_types::Digest32;
32
use ergo_chain_types::EcPoint;
33
use impl_trait_for_tuples::impl_for_tuples;
34
use sigma_util::AsVecI8;
35
use sigma_util::AsVecU8;
36

37
mod constant_placeholder;
38

39
pub use constant_placeholder::*;
40

41
use super::avl_tree_data::AvlTreeData;
42
use super::avl_tree_data::AvlTreeFlags;
43
use super::value::NativeColl;
44
use super::value::StoreWrapped;
45
use super::value::Value;
46

47
use thiserror::Error;
48

49
#[derive(PartialEq, Eq, Clone)]
50
/// Constant
51
pub struct Constant {
52
    /// Constant type
53
    pub tpe: SType,
54
    /// Constant value
55
    pub v: Literal,
56
}
57

58
#[derive(PartialEq, Eq, Clone)]
59
/// Possible values for `Constant`
60
pub enum Literal {
61
    /// Unit
62
    Unit,
63
    /// Boolean
64
    Boolean(bool),
65
    /// i8
66
    Byte(i8),
67
    /// Short
68
    Short(i16),
69
    /// Int
70
    Int(i32),
71
    /// Long
72
    Long(i64),
73
    /// String type
74
    String(Arc<str>),
75
    /// Big integer
76
    BigInt(BigInt256),
77
    /// Sigma property
78
    SigmaProp(Box<SigmaProp>),
79
    /// GroupElement
80
    GroupElement(Arc<EcPoint>),
81
    /// AVL tree
82
    AvlTree(Box<AvlTreeData>),
83
    /// Ergo box
84
    CBox(Ref<'static, ErgoBox>),
85
    /// Collection
86
    Coll(CollKind<Literal>),
87
    /// Option type
88
    Opt(Box<Option<Literal>>),
89
    /// Tuple (arbitrary type values)
90
    Tup(TupleItems<Literal>),
91
}
92

93
impl core::fmt::Debug for Constant {
94
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
3✔
95
        format!("{:?}: {:?}", self.v, self.tpe).fmt(f)
9✔
96
    }
97
}
98

99
impl core::fmt::Display for Constant {
100
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
×
101
        self.v.fmt(f)
×
102
    }
103
}
104

105
impl core::fmt::Debug for Literal {
106
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
4✔
107
        match self {
7✔
108
            Literal::Coll(CollKind::NativeColl(NativeColl::CollByte(i8_bytes))) => {
1✔
109
                base16::encode_lower(&i8_bytes.as_vec_u8()).fmt(f)
3✔
110
            }
111
            Literal::Coll(CollKind::WrappedColl { elem_tpe: _, items }) => items.fmt(f),
1✔
112
            Literal::Opt(boxed_opt) => boxed_opt.fmt(f),
×
113
            Literal::Tup(items) => items.fmt(f),
1✔
114
            Literal::Unit => ().fmt(f),
×
115
            Literal::Boolean(v) => v.fmt(f),
3✔
116
            Literal::Byte(v) => v.fmt(f),
1✔
117
            Literal::Short(v) => v.fmt(f),
1✔
118
            Literal::Int(v) => v.fmt(f),
4✔
119
            Literal::Long(v) => v.fmt(f),
2✔
120
            Literal::BigInt(v) => v.fmt(f),
1✔
121
            Literal::SigmaProp(v) => v.fmt(f),
1✔
122
            Literal::GroupElement(v) => v.fmt(f),
1✔
123
            Literal::AvlTree(v) => v.fmt(f),
×
124
            Literal::CBox(v) => v.fmt(f),
×
125
            Literal::String(v) => v.fmt(f),
×
126
        }
127
    }
128
}
129

130
impl core::fmt::Display for Literal {
131
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
×
132
        match self {
×
133
            Literal::Coll(CollKind::NativeColl(NativeColl::CollByte(i8_bytes))) => {
×
134
                write!(f, "Coll[Byte](")?;
×
135
                for (i, b) in i8_bytes.iter().enumerate() {
×
136
                    if i > 0 {
×
137
                        write!(f, ", ")?;
×
138
                    }
139
                    write!(f, "{}", b)?;
×
140
                }
141
                write!(f, ")")
×
142
            }
143
            Literal::Coll(CollKind::WrappedColl { elem_tpe, items }) => {
×
144
                write!(f, "Coll[{}](", elem_tpe)?;
×
145
                for (i, item) in items.iter().enumerate() {
×
146
                    if i > 0 {
×
147
                        write!(f, ", ")?;
×
148
                    }
149
                    item.fmt(f)?;
×
150
                }
151
                write!(f, ")")
×
152
            }
153
            Literal::Opt(boxed_opt) => {
×
154
                if let Some(v) = &**boxed_opt {
×
155
                    write!(f, "Some(")?;
×
156
                    v.fmt(f)?;
×
157
                    write!(f, ")")
×
158
                } else {
159
                    write!(f, "None")
×
160
                }
161
            }
162
            Literal::Tup(items) => {
×
163
                write!(f, "(")?;
×
164
                for (i, item) in items.iter().enumerate() {
×
165
                    if i > 0 {
×
166
                        write!(f, ", ")?;
×
167
                    }
168
                    item.fmt(f)?;
×
169
                }
170
                write!(f, ")")
×
171
            }
172
            Literal::Unit => write!(f, "()"),
×
173
            Literal::Boolean(v) => v.fmt(f),
×
174
            Literal::Byte(v) => v.fmt(f),
×
175
            Literal::Short(v) => v.fmt(f),
×
176
            Literal::Int(v) => v.fmt(f),
×
177
            Literal::Long(v) => write!(f, "{}L", v),
×
178
            Literal::BigInt(v) => v.fmt(f),
×
179
            Literal::SigmaProp(v) => v.fmt(f),
×
180
            Literal::GroupElement(v) => v.fmt(f),
×
181
            Literal::AvlTree(v) => write!(f, "AvlTree({:?})", v),
×
182
            Literal::CBox(v) => write!(f, "ErgoBox({:?})", v),
×
183
            Literal::String(v) => write!(f, "String({v})"),
×
184
        }
185
    }
186
}
187

188
impl From<()> for Literal {
189
    fn from(_: ()) -> Literal {
×
190
        Literal::Unit
×
191
    }
192
}
193

194
impl From<bool> for Literal {
195
    fn from(v: bool) -> Literal {
5✔
196
        Literal::Boolean(v)
5✔
197
    }
198
}
199

200
impl From<i8> for Literal {
201
    fn from(v: i8) -> Literal {
5✔
202
        Literal::Byte(v)
5✔
203
    }
204
}
205

206
impl From<i16> for Literal {
207
    fn from(v: i16) -> Literal {
5✔
208
        Literal::Short(v)
5✔
209
    }
210
}
211

212
impl From<i32> for Literal {
213
    fn from(v: i32) -> Literal {
6✔
214
        Literal::Int(v)
6✔
215
    }
216
}
217

218
impl From<i64> for Literal {
219
    fn from(v: i64) -> Literal {
6✔
220
        Literal::Long(v)
6✔
221
    }
222
}
223

224
impl From<BigInt256> for Literal {
225
    fn from(v: BigInt256) -> Literal {
×
226
        Literal::BigInt(v)
×
227
    }
228
}
229

230
impl From<SigmaProp> for Literal {
231
    fn from(v: SigmaProp) -> Literal {
8✔
232
        Literal::SigmaProp(Box::new(v))
8✔
233
    }
234
}
235

236
impl From<EcPoint> for Literal {
237
    fn from(v: EcPoint) -> Literal {
5✔
238
        Literal::GroupElement(Arc::new(v))
5✔
239
    }
240
}
241

242
impl From<Ref<'_, EcPoint>> for Literal {
243
    fn from(value: Ref<'_, EcPoint>) -> Self {
1✔
244
        Literal::GroupElement(value.to_arc())
2✔
245
    }
246
}
247

248
impl From<Ref<'static, ErgoBox>> for Literal {
249
    fn from(b: Ref<'static, ErgoBox>) -> Self {
×
250
        Literal::CBox(b)
×
251
    }
252
}
253

254
impl From<ErgoBox> for Literal {
255
    fn from(b: ErgoBox) -> Self {
×
256
        Literal::CBox(Arc::new(b).into())
×
257
    }
258
}
259

260
impl From<Vec<u8>> for Literal {
261
    fn from(v: Vec<u8>) -> Self {
3✔
262
        Literal::Coll(CollKind::NativeColl(NativeColl::CollByte(
3✔
263
            v.as_vec_i8().into(),
6✔
264
        ))) // TODO: optimize
265
    }
266
}
267

268
impl From<Digest32> for Literal {
269
    fn from(v: Digest32) -> Self {
1✔
270
        let bytes: Vec<u8> = v.into();
1✔
271
        Literal::Coll(CollKind::NativeColl(NativeColl::CollByte(
1✔
272
            bytes.as_vec_i8().into(), // TODO: optimize
2✔
273
        )))
274
    }
275
}
276

277
impl From<TokenId> for Literal {
278
    fn from(v: TokenId) -> Self {
×
279
        Digest32::from(v).into()
×
280
    }
281
}
282

283
impl From<Vec<i8>> for Literal {
284
    fn from(v: Vec<i8>) -> Self {
5✔
285
        Literal::Coll(CollKind::NativeColl(NativeColl::CollByte(v.into()))) // TODO
5✔
286
    }
287
}
288

289
impl<T: LiftIntoSType + StoreWrapped + Into<Literal>> From<Vec<T>> for Literal {
290
    fn from(v: Vec<T>) -> Self {
3✔
291
        Literal::Coll(CollKind::WrappedColl {
6✔
292
            elem_tpe: T::stype(),
3✔
293
            items: v.into_iter().map(|i| i.into()).collect(),
12✔
294
        })
295
    }
296
}
297

298
impl<T: LiftIntoSType + Into<Literal>> From<Option<T>> for Literal {
299
    fn from(opt: Option<T>) -> Self {
×
300
        Literal::Opt(Box::new(opt.map(|e| e.into())))
×
301
    }
302
}
303

304
impl<'ctx> TryFrom<Value<'ctx>> for Constant {
305
    type Error = String;
306
    #[allow(clippy::unwrap_used)]
307
    fn try_from(value: Value<'ctx>) -> Result<Self, Self::Error> {
1✔
308
        match value {
2✔
309
            Value::Boolean(b) => Ok(Constant::from(b)),
2✔
310
            Value::Byte(b) => Ok(Constant::from(b)),
2✔
311
            Value::Short(s) => Ok(Constant::from(s)),
2✔
312
            Value::Int(i) => Ok(Constant::from(i)),
2✔
313
            Value::Long(l) => Ok(Constant::from(l)),
2✔
314
            Value::BigInt(b) => Ok(Constant::from(b)),
2✔
315
            Value::Unit => Ok(Constant {
×
316
                tpe: SType::SUnit,
×
317
                v: Literal::Unit,
×
318
            }),
319
            Value::SigmaProp(s) => Ok(Constant::from(*s)),
2✔
320
            Value::GroupElement(e) => Ok(Constant::from(e)),
2✔
321
            Value::CBox(i) => Ok(Constant::from(i.to_static())),
×
322
            Value::Coll(coll) => {
1✔
323
                let (v, tpe) = match coll {
2✔
324
                    CollKind::NativeColl(n) => (
2✔
325
                        Literal::Coll(CollKind::NativeColl(n)),
1✔
326
                        SType::SColl(Arc::new(SType::SByte)),
2✔
327
                    ),
328
                    CollKind::WrappedColl { elem_tpe, items } => {
1✔
329
                        let new_items = items
2✔
330
                            .iter()
331
                            .map(|v| Ok(Constant::try_from(v.clone())?.v))
2✔
332
                            .collect::<Result<Arc<[_]>, String>>()?;
333

334
                        (
335
                            Literal::Coll(CollKind::WrappedColl {
1✔
336
                                elem_tpe: elem_tpe.clone(),
1✔
337
                                items: new_items,
1✔
338
                            }),
339
                            SType::SColl(Arc::new(elem_tpe)),
2✔
340
                        )
341
                    }
342
                };
343
                Ok(Constant { v, tpe })
1✔
344
            }
345
            Value::Opt(lit) => match *lit {
×
346
                Some(v) => {
×
347
                    let c = Constant::try_from(v)?;
×
348
                    Ok(Constant {
×
349
                        v: Literal::Opt(Box::new(Some(c.v))),
×
350
                        tpe: c.tpe,
×
351
                    })
352
                }
353
                None => Err("Can't convert from Value::Opt(None) to Constant".into()),
×
354
            },
355
            Value::Tup(t) => {
1✔
356
                if let Ok(t) = t.try_mapped::<_, _, String>(|v| {
3✔
357
                    let c = Constant::try_from(v)?;
1✔
358
                    Ok((c.v, c.tpe))
1✔
359
                }) {
360
                    let tuple_items = t.mapped_ref(|(l, _)| l.clone());
3✔
361
                    let tuple_item_types = SType::STuple(STuple {
1✔
362
                        items: t.mapped(|(_, tpe)| tpe),
3✔
363
                    });
364
                    Ok(Constant {
1✔
365
                        v: Literal::Tup(tuple_items),
1✔
366
                        tpe: tuple_item_types,
×
367
                    })
368
                } else {
369
                    Err("Can't convert Value:Tup element".into())
×
370
                }
371
            }
372
            Value::AvlTree(a) => Ok(Constant::from(*a)),
×
373
            Value::String(s) => Ok(Constant::from(s)),
×
374
            Value::Context => Err("Cannot convert Value::Context into Constant".into()),
×
375
            Value::Header(_) => Err("Cannot convert Value::Header(_) into Constant".into()),
×
376
            Value::PreHeader(_) => Err("Cannot convert Value::PreHeader(_) into Constant".into()),
×
377
            Value::Global => Err("Cannot convert Value::Global into Constant".into()),
×
378
            Value::Lambda(_) => Err("Cannot convert Value::Lambda(_) into Constant".into()),
×
379
        }
380
    }
381
}
382

383
impl From<()> for Constant {
384
    fn from(_: ()) -> Self {
1✔
385
        Constant {
386
            tpe: SType::SUnit,
387
            v: Literal::Unit,
388
        }
389
    }
390
}
391

392
impl From<bool> for Constant {
393
    fn from(v: bool) -> Self {
5✔
394
        Constant {
395
            tpe: bool::stype(),
5✔
396
            v: v.into(),
5✔
397
        }
398
    }
399
}
400

401
impl From<i8> for Constant {
402
    fn from(v: i8) -> Self {
5✔
403
        Constant {
404
            tpe: i8::stype(),
5✔
405
            v: v.into(),
5✔
406
        }
407
    }
408
}
409

410
impl From<i16> for Constant {
411
    fn from(v: i16) -> Self {
5✔
412
        Constant {
413
            tpe: i16::stype(),
5✔
414
            v: v.into(),
5✔
415
        }
416
    }
417
}
418

419
impl From<i32> for Constant {
420
    fn from(v: i32) -> Self {
6✔
421
        Constant {
422
            tpe: i32::stype(),
6✔
423
            v: v.into(),
6✔
424
        }
425
    }
426
}
427

428
impl From<i64> for Constant {
429
    fn from(v: i64) -> Self {
6✔
430
        Constant {
431
            tpe: i64::stype(),
6✔
432
            v: v.into(),
6✔
433
        }
434
    }
435
}
436

437
impl From<SigmaProp> for Constant {
438
    fn from(v: SigmaProp) -> Self {
8✔
439
        Constant {
440
            tpe: SType::SSigmaProp,
441
            v: v.into(),
8✔
442
        }
443
    }
444
}
445

446
impl From<EcPoint> for Constant {
447
    fn from(v: EcPoint) -> Constant {
5✔
448
        Constant {
449
            tpe: SType::SGroupElement,
450
            v: v.into(),
5✔
451
        }
452
    }
453
}
454

455
impl From<Ref<'_, EcPoint>> for Constant {
456
    fn from(v: Ref<'_, EcPoint>) -> Self {
1✔
457
        Constant {
458
            tpe: SType::SGroupElement,
459
            v: v.into(),
1✔
460
        }
461
    }
462
}
463

464
impl From<&'static ErgoBox> for Constant {
465
    fn from(b: &'static ErgoBox) -> Self {
×
466
        Constant {
467
            tpe: SType::SBox,
468
            v: Literal::CBox(Ref::Borrowed(b)),
×
469
        }
470
    }
471
}
472

473
impl From<ErgoBox> for Constant {
474
    fn from(b: ErgoBox) -> Self {
1✔
475
        Constant {
476
            tpe: SType::SBox,
477
            v: Literal::CBox(Arc::new(b).into()),
2✔
478
        }
479
    }
480
}
481

482
impl From<Ref<'static, ErgoBox>> for Constant {
483
    fn from(b: Ref<'static, ErgoBox>) -> Self {
×
484
        Constant {
485
            tpe: SType::SBox,
486
            v: Literal::CBox(b),
×
487
        }
488
    }
489
}
490

491
impl From<Vec<u8>> for Constant {
492
    fn from(v: Vec<u8>) -> Self {
3✔
493
        Constant {
494
            tpe: SType::SColl(Arc::new(SType::SByte)),
6✔
495
            v: v.into(),
3✔
496
        }
497
    }
498
}
499

500
impl From<Digest32> for Constant {
501
    fn from(v: Digest32) -> Self {
1✔
502
        Constant {
503
            tpe: SType::SColl(Arc::new(SType::SByte)),
1✔
504
            v: v.into(),
1✔
505
        }
506
    }
507
}
508

509
impl From<TokenId> for Constant {
510
    fn from(v: TokenId) -> Self {
1✔
511
        Digest32::from(v).into()
1✔
512
    }
513
}
514

515
impl From<Vec<i8>> for Constant {
516
    fn from(v: Vec<i8>) -> Self {
5✔
517
        Constant {
518
            tpe: SType::SColl(Arc::new(SType::SByte)),
10✔
519
            v: v.into(),
5✔
520
        }
521
    }
522
}
523

524
impl<T: LiftIntoSType + StoreWrapped + Into<Constant>> From<Vec<T>> for Constant {
525
    fn from(v: Vec<T>) -> Self {
14✔
526
        Constant {
527
            tpe: Vec::<T>::stype(),
14✔
528
            v: Literal::Coll(CollKind::WrappedColl {
14✔
529
                elem_tpe: T::stype(),
530
                items: v.into_iter().map(|i| i.into().v).collect(),
531
            }),
532
        }
533
    }
534
}
535

536
impl<T: LiftIntoSType + Into<Constant>> From<Option<T>> for Constant {
537
    fn from(opt: Option<T>) -> Self {
6✔
538
        Constant {
539
            tpe: SType::SOption(Arc::new(T::stype())),
12✔
540
            v: Literal::Opt(Box::new(opt.map(|e| e.into().v))),
24✔
541
        }
542
    }
543
}
544

545
impl From<ProveDlog> for Constant {
546
    fn from(v: ProveDlog) -> Self {
8✔
547
        Constant::from(SigmaProp::from(SigmaBoolean::from(
8✔
548
            SigmaProofOfKnowledgeTree::from(v),
8✔
549
        )))
550
    }
551
}
552

553
impl From<ProveDhTuple> for Constant {
554
    fn from(dht: ProveDhTuple) -> Self {
3✔
555
        Constant::from(SigmaProp::from(SigmaBoolean::from(
3✔
556
            SigmaProofOfKnowledgeTree::from(dht),
3✔
557
        )))
558
    }
559
}
560

561
impl From<SigmaBoolean> for Constant {
562
    fn from(sb: SigmaBoolean) -> Self {
1✔
563
        Constant::from(SigmaProp::from(sb))
1✔
564
    }
565
}
566

567
impl From<BigInt256> for Constant {
568
    fn from(b: BigInt256) -> Self {
6✔
569
        Constant {
570
            tpe: SType::SBigInt,
571
            v: Literal::BigInt(b),
6✔
572
        }
573
    }
574
}
575

576
impl From<AvlTreeData> for Constant {
577
    fn from(a: AvlTreeData) -> Self {
2✔
578
        Constant {
579
            tpe: SType::SAvlTree,
580
            v: Literal::AvlTree(Box::new(a)),
2✔
581
        }
582
    }
583
}
584

585
impl From<AvlTreeFlags> for Constant {
586
    fn from(a: AvlTreeFlags) -> Self {
1✔
587
        Constant {
588
            tpe: SType::SByte,
589
            v: Literal::Byte(a.serialize() as i8),
2✔
590
        }
591
    }
592
}
593

594
impl From<ADDigest> for Constant {
595
    fn from(a: ADDigest) -> Self {
1✔
596
        Constant {
597
            tpe: SType::SColl(Arc::new(SType::SByte)),
1✔
598
            v: Literal::Coll(CollKind::NativeColl(NativeColl::CollByte(
1✔
599
                a.0.iter().map(|&i| i as i8).collect(),
600
            ))),
601
        }
602
    }
603
}
604

605
impl From<Arc<str>> for Constant {
606
    fn from(s: Arc<str>) -> Self {
×
607
        Constant {
608
            tpe: SType::SString,
609
            v: Literal::String(s),
×
610
        }
611
    }
612
}
613

614
impl From<String> for Constant {
615
    fn from(s: String) -> Self {
1✔
616
        Constant {
617
            tpe: SType::SString,
618
            v: Literal::String(s.into()),
2✔
619
        }
620
    }
621
}
622

623
#[allow(clippy::unwrap_used)]
624
#[allow(clippy::from_over_into)]
625
#[impl_for_tuples(2, 4)]
626
impl Into<Constant> for Tuple {
627
    fn into(self) -> Constant {
6✔
628
        let constants: Vec<Constant> = [for_tuples!(  #( Tuple.into() ),* )].to_vec();
6✔
629
        let (types, values): (Vec<SType>, Vec<Literal>) =
6✔
630
            constants.into_iter().map(|c| (c.tpe, c.v)).unzip();
631
        Constant {
632
            tpe: SType::STuple(types.try_into().unwrap()),
12✔
633
            v: Literal::Tup(values.try_into().unwrap()),
13✔
634
        }
635
    }
636
}
637

638
/// Extract value wrapped in a type
639
pub trait TryExtractInto<F> {
640
    /// Extract value of the given type from any type (e.g. ['Constant'], [`super::value::Value`])
641
    /// on which [`TryExtractFrom`] is implemented
642
    fn try_extract_into<T: TryExtractFrom<F>>(self) -> Result<T, TryExtractFromError>;
643
}
644

645
impl<F> TryExtractInto<F> for F {
646
    fn try_extract_into<T: TryExtractFrom<F>>(self) -> Result<T, TryExtractFromError> {
76✔
647
        T::try_extract_from(self)
76✔
648
    }
649
}
650

651
/// Underlying type is different from requested value type
652
#[derive(Error, PartialEq, Eq, Debug, Clone)]
653
#[error("Failed TryExtractFrom: {0}")]
654
pub struct TryExtractFromError(pub String);
655

656
/// Extract underlying value if type matches
657
pub trait TryExtractFrom<T>: Sized {
658
    /// Extract the value or return an error if type does not match
659
    fn try_extract_from(v: T) -> Result<Self, TryExtractFromError>;
660
}
661

662
impl<T: TryExtractFrom<Literal>> TryExtractFrom<Constant> for T {
663
    fn try_extract_from(cv: Constant) -> Result<Self, TryExtractFromError> {
27✔
664
        T::try_extract_from(cv.v)
27✔
665
    }
666
}
667

668
impl TryExtractFrom<Literal> for () {
669
    fn try_extract_from(cv: Literal) -> Result<(), TryExtractFromError> {
1✔
670
        match cv {
1✔
671
            Literal::Unit => Ok(()),
1✔
672
            _ => Err(TryExtractFromError(format!(
×
673
                "expected Unit, found {:?}",
674
                cv
675
            ))),
676
        }
677
    }
678
}
679

680
impl TryExtractFrom<Literal> for bool {
681
    fn try_extract_from(cv: Literal) -> Result<bool, TryExtractFromError> {
5✔
682
        match cv {
5✔
683
            Literal::Boolean(v) => Ok(v),
5✔
684
            _ => Err(TryExtractFromError(format!(
×
685
                "expected bool, found {:?}",
686
                cv
687
            ))),
688
        }
689
    }
690
}
691

692
impl TryExtractFrom<Literal> for i8 {
693
    fn try_extract_from(cv: Literal) -> Result<i8, TryExtractFromError> {
5✔
694
        match cv {
5✔
695
            Literal::Byte(v) => Ok(v),
5✔
696
            _ => Err(TryExtractFromError(format!("expected i8, found {:?}", cv))),
×
697
        }
698
    }
699
}
700

701
impl TryExtractFrom<Literal> for i16 {
702
    fn try_extract_from(cv: Literal) -> Result<i16, TryExtractFromError> {
1✔
703
        match cv {
1✔
704
            Literal::Short(v) => Ok(v),
1✔
705
            _ => Err(TryExtractFromError(format!("expected i16, found {:?}", cv))),
×
706
        }
707
    }
708
}
709

710
impl TryExtractFrom<Literal> for i32 {
711
    fn try_extract_from(cv: Literal) -> Result<i32, TryExtractFromError> {
1✔
712
        match cv {
1✔
713
            Literal::Int(v) => Ok(v),
1✔
714
            _ => Err(TryExtractFromError(format!("expected i32, found {:?}", cv))),
×
715
        }
716
    }
717
}
718

719
impl TryExtractFrom<Literal> for i64 {
720
    fn try_extract_from(cv: Literal) -> Result<i64, TryExtractFromError> {
1✔
721
        match cv {
1✔
722
            Literal::Long(v) => Ok(v),
1✔
723
            _ => Err(TryExtractFromError(format!("expected i64, found {:?}", cv))),
×
724
        }
725
    }
726
}
727

728
impl TryExtractFrom<Literal> for EcPoint {
729
    fn try_extract_from(cv: Literal) -> Result<EcPoint, TryExtractFromError> {
1✔
730
        match cv {
1✔
731
            Literal::GroupElement(v) => Ok((*v).clone()),
1✔
732
            _ => Err(TryExtractFromError(format!(
×
733
                "expected EcPoint, found {:?}",
734
                cv
735
            ))),
736
        }
737
    }
738
}
739

740
impl TryExtractFrom<Literal> for SigmaProp {
741
    fn try_extract_from(cv: Literal) -> Result<SigmaProp, TryExtractFromError> {
1✔
742
        match cv {
1✔
743
            Literal::SigmaProp(v) => Ok(*v),
3✔
744
            _ => Err(TryExtractFromError(format!(
×
745
                "expected SigmaProp, found {:?}",
746
                cv
747
            ))),
748
        }
749
    }
750
}
751

752
impl TryExtractFrom<Literal> for Ref<'static, ErgoBox> {
753
    fn try_extract_from(c: Literal) -> Result<Self, TryExtractFromError> {
×
754
        match c {
×
755
            Literal::CBox(b) => Ok(b),
×
756
            _ => Err(TryExtractFromError(format!(
×
757
                "expected ErgoBox, found {:?}",
758
                c
759
            ))),
760
        }
761
    }
762
}
763

764
impl TryExtractFrom<Literal> for ErgoBox {
765
    fn try_extract_from(c: Literal) -> Result<Self, TryExtractFromError> {
×
766
        match c {
×
767
            Literal::CBox(b) => Ok((*b).clone()),
×
768
            _ => Err(TryExtractFromError(format!(
×
769
                "expected ErgoBox, found {:?}",
770
                c
771
            ))),
772
        }
773
    }
774
}
775

776
impl<T: TryExtractFrom<Literal> + StoreWrapped> TryExtractFrom<Literal> for Vec<T> {
777
    fn try_extract_from(c: Literal) -> Result<Self, TryExtractFromError> {
7✔
778
        match c {
7✔
779
            Literal::Coll(coll) => match coll {
7✔
780
                CollKind::WrappedColl {
7✔
781
                    elem_tpe: _,
×
782
                    items: v,
×
783
                } => v.iter().cloned().map(T::try_extract_from).collect(),
×
784
                _ => Err(TryExtractFromError(format!(
×
785
                    "expected {:?}, found {:?}",
×
786
                    core::any::type_name::<Self>(),
×
787
                    coll
×
788
                ))),
789
            },
790
            _ => Err(TryExtractFromError(format!(
×
791
                "expected {:?}, found {:?}",
×
792
                core::any::type_name::<Self>(),
×
793
                c
×
794
            ))),
795
        }
796
    }
797
}
798

799
impl TryExtractFrom<Literal> for Vec<i8> {
800
    fn try_extract_from(v: Literal) -> Result<Self, TryExtractFromError> {
2✔
801
        match v {
2✔
802
            Literal::Coll(v) => match v {
2✔
803
                CollKind::NativeColl(NativeColl::CollByte(bs)) => Ok(bs.iter().copied().collect()), // TODO: optimize
2✔
804
                _ => Err(TryExtractFromError(format!(
×
805
                    "expected {:?}, found {:?}",
806
                    core::any::type_name::<Self>(),
×
807
                    v
808
                ))),
809
            },
810
            _ => Err(TryExtractFromError(format!(
2✔
811
                "expected {:?}, found {:?}",
812
                core::any::type_name::<Self>(),
2✔
813
                v
814
            ))),
815
        }
816
    }
817
}
818

819
impl TryExtractFrom<Literal> for Vec<u8> {
820
    fn try_extract_from(v: Literal) -> Result<Self, TryExtractFromError> {
2✔
821
        use sigma_util::FromVecI8;
822
        Vec::<i8>::try_extract_from(v).map(Vec::<u8>::from_vec_i8)
2✔
823
    }
824
}
825

826
impl TryExtractFrom<Literal> for Digest32 {
827
    fn try_extract_from(v: Literal) -> Result<Self, TryExtractFromError> {
1✔
828
        use sigma_util::FromVecI8;
829
        let bytes = Vec::<i8>::try_extract_from(v).map(Vec::<u8>::from_vec_i8)?;
1✔
830
        Digest32::try_from(bytes).map_err(|e| {
2✔
831
            TryExtractFromError(format!("failed to extract Digest32 with error: {:?}", e))
×
832
        })
833
    }
834
}
835

836
impl TryExtractFrom<Literal> for TokenId {
837
    fn try_extract_from(v: Literal) -> Result<Self, TryExtractFromError> {
1✔
838
        Digest32::try_extract_from(v).map(Into::into)
1✔
839
    }
840
}
841

842
impl TryExtractFrom<Literal> for Literal {
843
    fn try_extract_from(v: Literal) -> Result<Self, TryExtractFromError> {
×
844
        Ok(v)
×
845
    }
846
}
847

848
impl TryExtractFrom<Literal> for BigInt256 {
849
    fn try_extract_from(v: Literal) -> Result<Self, TryExtractFromError> {
1✔
850
        match v {
1✔
851
            Literal::BigInt(bi) => Ok(bi),
1✔
852
            _ => Err(TryExtractFromError(format!(
×
853
                "expected {:?}, found {:?}",
854
                core::any::type_name::<Self>(),
×
855
                v
856
            ))),
857
        }
858
    }
859
}
860

861
impl TryExtractFrom<Literal> for String {
862
    fn try_extract_from(v: Literal) -> Result<Self, TryExtractFromError> {
1✔
863
        match v {
1✔
864
            Literal::String(s) => Ok(String::from(&*s)),
1✔
865
            _ => Err(TryExtractFromError(format!(
×
866
                "expected {:?}, found {:?}",
867
                core::any::type_name::<Self>(),
×
868
                v
869
            ))),
870
        }
871
    }
872
}
873

874
impl TryExtractFrom<Literal> for AvlTreeData {
875
    fn try_extract_from(v: Literal) -> Result<Self, TryExtractFromError> {
×
876
        match v {
×
877
            Literal::AvlTree(a) => Ok(*a),
×
878
            _ => Err(TryExtractFromError(format!(
×
879
                "expected {:?}, found {:?}",
880
                core::any::type_name::<Self>(),
×
881
                v
882
            ))),
883
        }
884
    }
885
}
886

887
impl<T: TryExtractFrom<Literal>> TryExtractFrom<Literal> for Option<T> {
888
    fn try_extract_from(v: Literal) -> Result<Self, TryExtractFromError> {
4✔
889
        match v {
4✔
890
            Literal::Opt(opt) => opt.map(T::try_extract_from).transpose(),
12✔
891
            _ => Err(TryExtractFromError(format!(
×
892
                "expected Option, found {:?}",
×
893
                v
×
894
            ))),
895
        }
896
    }
897
}
898

899
#[impl_for_tuples(2, 4)]
900
impl TryExtractFrom<Literal> for Tuple {
901
    fn try_extract_from(v: Literal) -> Result<Self, TryExtractFromError> {
2✔
902
        match v {
2✔
903
            Literal::Tup(items) => {
2✔
904
                let mut iter = items.iter();
4✔
905
                Ok(for_tuples!( ( #(
2✔
906
                                Tuple::try_extract_from(
907
                                    iter
6✔
908
                                        .next()
909
                                        .cloned()
910
                                        .ok_or_else(|| TryExtractFromError("not enough items in STuple".to_string()))?
×
911
                                )?
912
                                ),* ) ))
×
913
            }
914
            _ => Err(TryExtractFromError(format!(
×
915
                "expected Context, found {:?}",
916
                v
917
            ))),
918
        }
919
    }
920
}
921

922
impl TryFrom<Literal> for ProveDlog {
923
    type Error = TryExtractFromError;
924
    fn try_from(cv: Literal) -> Result<Self, Self::Error> {
2✔
925
        match cv {
2✔
926
            Literal::SigmaProp(sp) => match sp.value() {
4✔
927
                SigmaBoolean::ProofOfKnowledge(SigmaProofOfKnowledgeTree::ProveDlog(
2✔
928
                    prove_dlog,
929
                )) => Ok(prove_dlog.clone()),
930
                _ => Err(TryExtractFromError(format!(
×
931
                    "expected ProveDlog, found {:?}",
932
                    sp
933
                ))),
934
            },
935
            _ => Err(TryExtractFromError(format!(
×
936
                "expected SigmaProp, found {:?}",
937
                cv
938
            ))),
939
        }
940
    }
941
}
942

943
impl Base16Str for &Constant {
944
    fn base16_str(&self) -> Result<String, SigmaSerializationError> {
×
945
        self.sigma_serialize_bytes()
×
946
            .map(|bytes| base16::encode_lower(&bytes))
×
947
    }
948
}
949

950
impl Base16Str for Constant {
951
    fn base16_str(&self) -> Result<String, SigmaSerializationError> {
1✔
952
        self.sigma_serialize_bytes()
1✔
953
            .map(|bytes| base16::encode_lower(&bytes))
2✔
954
    }
955
}
956

957
impl TryFrom<Base16DecodedBytes> for Constant {
958
    type Error = SigmaParsingError;
959

960
    fn try_from(value: Base16DecodedBytes) -> Result<Self, Self::Error> {
×
961
        Constant::sigma_parse_bytes(&value.0)
×
962
    }
963
}
964

965
#[cfg(feature = "arbitrary")]
966
#[allow(clippy::unwrap_used)]
967
#[allow(clippy::todo)]
968
/// Arbitrary impl
969
pub(crate) mod arbitrary {
970
    use core::convert::TryFrom;
971

972
    use super::*;
973
    use crate::mir::value::CollKind;
974
    use crate::types::stuple::STuple;
975
    use proptest::collection::vec;
976
    use proptest::prelude::*;
977

978
    extern crate derive_more;
979
    use derive_more::From;
980
    use derive_more::TryInto;
981

982
    fn primitive_type_value() -> BoxedStrategy<Constant> {
8✔
983
        prop_oneof![
71✔
984
            any::<bool>().prop_map_into(),
8✔
985
            any::<i8>().prop_map_into(),
16✔
986
            any::<i16>().prop_map_into(),
16✔
987
            any::<i32>().prop_map_into(),
16✔
988
            any::<i64>().prop_map_into(),
16✔
989
            any::<i64>().prop_map(|v| BigInt256::from(v).into()),
28✔
990
            any::<EcPoint>().prop_map_into(),
16✔
991
            any::<SigmaProp>().prop_map_into(),
16✔
992
            // although it's not strictly a primitive type, byte array is widely used as one
993
            vec(any::<i8>(), 0..100).prop_map_into(),
16✔
994
        ]
995
        .boxed()
996
    }
997

998
    fn coll_from_constant(c: Constant, length: usize) -> Constant {
5✔
999
        Constant {
1000
            tpe: SType::SColl(Arc::new(c.tpe.clone())),
10✔
1001
            v: Literal::Coll(if c.tpe == SType::SByte {
21✔
1002
                let mut values: Vec<i8> = Vec::with_capacity(length);
1003
                let byte: i8 = c.v.try_extract_into().unwrap();
1004
                for _ in 0..length {
1005
                    values.push(byte);
1006
                }
1007
                CollKind::NativeColl(NativeColl::CollByte(values.into())) // TODO: optimize
1008
            } else {
1009
                let mut values: Vec<Literal> = Vec::with_capacity(length);
1010
                for _ in 0..length {
1011
                    values.push(c.v.clone());
1012
                }
1013
                CollKind::WrappedColl {
1014
                    elem_tpe: c.tpe,
1015
                    items: values.into(),
1016
                }
1017
            }),
1018
        }
1019
    }
1020

1021
    fn const_with_type(tpe: SType) -> BoxedStrategy<Constant> {
8✔
1022
        match tpe {
8✔
1023
            SType::SAny => any::<Constant>(),
4✔
1024
            SType::SBoolean => any::<bool>().prop_map_into().boxed(),
4✔
1025
            SType::SByte => any::<i8>().prop_map_into().boxed(),
2✔
1026
            SType::SShort => any::<i16>().prop_map_into().boxed(),
2✔
1027
            SType::SInt => any::<i32>().prop_map_into().boxed(),
2✔
1028
            SType::SLong => any::<i64>().prop_map_into().boxed(),
2✔
1029
            SType::SBigInt => any::<i64>().prop_map(|v| BigInt256::from(v).into()).boxed(),
4✔
1030
            SType::SGroupElement => any::<EcPoint>().prop_map_into().boxed(),
2✔
1031
            SType::SSigmaProp => any::<SigmaProp>().prop_map_into().boxed(),
17✔
1032
            SType::SBox => any::<ErgoBox>().prop_map_into().boxed(),
2✔
1033
            SType::SAvlTree => any::<AvlTreeData>().prop_map_into().boxed(),
2✔
1034
            // SType::SOption(tpe) =>
1035
            SType::SOption(tpe) => match *tpe {
×
1036
                SType::SBoolean => any::<Option<bool>>().prop_map_into().boxed(),
×
1037
                SType::SByte => any::<Option<i8>>().prop_map_into().boxed(),
×
1038
                SType::SShort => any::<Option<i16>>().prop_map_into().boxed(),
×
1039
                SType::SInt => any::<Option<i32>>().prop_map_into().boxed(),
×
1040
                SType::SLong => any::<Option<i64>>().prop_map_into().boxed(),
×
1041
                _ => todo!(),
1042
            },
1043
            SType::SColl(elem_tpe) => match *elem_tpe {
4✔
1044
                SType::SBoolean => vec(any::<bool>(), 0..400).prop_map_into().boxed(),
4✔
1045
                SType::SByte => vec(any::<u8>(), 0..400).prop_map_into().boxed(),
2✔
1046
                SType::SShort => vec(any::<i16>(), 0..400).prop_map_into().boxed(),
×
1047
                SType::SInt => vec(any::<i32>(), 0..400).prop_map_into().boxed(),
2✔
1048
                SType::SLong => vec(any::<i64>(), 0..400).prop_map_into().boxed(),
2✔
1049
                SType::SSigmaProp => vec(any::<SigmaProp>(), 0..3).prop_map_into().boxed(),
×
1050
                _ => todo!(),
1051
            },
1052
            // SType::STuple(_) => {}
1053
            _ => todo!("{0:?} not yet implemented", tpe),
1054
        }
1055
    }
1056

1057
    impl Default for ArbConstantParams {
1058
        fn default() -> Self {
8✔
1059
            ArbConstantParams::AnyWithDepth(1)
8✔
1060
        }
1061
    }
1062

1063
    /// Parameters for arbitrary Constant generation
1064
    #[derive(PartialEq, Eq, Debug, Clone, From, TryInto)]
1065
    pub enum ArbConstantParams {
1066
        /// Constant of any type with a structrure of a given depth
1067
        AnyWithDepth(u8),
1068
        /// Constant of a given type
1069
        Exact(SType),
1070
    }
1071

1072
    impl Arbitrary for Constant {
1073
        type Parameters = ArbConstantParams;
1074
        type Strategy = BoxedStrategy<Self>;
1075

1076
        fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
9✔
1077
            match args {
8✔
1078
                ArbConstantParams::AnyWithDepth(depth) => {
8✔
1079
                    prop_oneof![primitive_type_value().prop_recursive(
15✔
1080
                        depth as u32,
9✔
1081
                        16,
1082
                        8,
1083
                        |elem| {
10✔
1084
                            prop_oneof![
40✔
1085
                                // Coll[_]
1086
                                elem.clone().prop_map(|c| coll_from_constant(c, 0)),
28✔
1087
                                elem.clone().prop_map(|c| coll_from_constant(c, 1)),
29✔
1088
                                elem.clone().prop_map(|c| coll_from_constant(c, 2)),
24✔
1089
                                elem.clone().prop_map(|c| coll_from_constant(c, 10)),
24✔
1090
                                // no Option[_] since it cannot be serialized (for now)
1091
                                // // Some(v)
1092
                                // elem.clone().prop_map(|c| Constant {
1093
                                //     tpe: SType::SOption(Box::new(c.tpe)),
1094
                                //     v: Value::Opt(Box::new(Some(c.v)))
1095
                                // }),
1096
                                // // None
1097
                                // elem.prop_map(|c| Constant {
1098
                                //     tpe: SType::SOption(Box::new(c.tpe)),
1099
                                //     v: Value::Opt(Box::new(None))
1100
                                // })
1101

1102
                                // Tuple
1103
                                vec(elem, 2..=4).prop_map(|constants| Constant {
21✔
1104
                                    tpe: SType::STuple(
12✔
1105
                                        STuple::try_from(
6✔
1106
                                            constants
12✔
1107
                                                .clone()
1108
                                                .into_iter()
1109
                                                .map(|c| c.tpe)
12✔
1110
                                                .collect::<Vec<SType>>()
1111
                                        )
1112
                                        .unwrap()
1113
                                    ),
1114
                                    v: Literal::Tup(
6✔
1115
                                        constants
12✔
1116
                                            .into_iter()
1117
                                            .map(|c| c.v)
12✔
1118
                                            .collect::<Vec<Literal>>()
1119
                                            .try_into()
1120
                                            .unwrap()
1121
                                    )
1122
                                }),
1123
                            ]
1124
                        }
1125
                    )]
1126
                    .boxed()
1127
                }
1128
                ArbConstantParams::Exact(tpe) => const_with_type(tpe),
8✔
1129
            }
1130
        }
1131
    }
1132
}
1133

1134
#[allow(clippy::unwrap_used)]
1135
#[cfg(test)]
1136
#[cfg(feature = "arbitrary")]
1137
#[allow(clippy::panic)]
1138
pub mod tests {
1139
    use super::*;
1140
    use core::fmt;
1141
    use proptest::prelude::*;
1142

1143
    fn test_constant_roundtrip<T>(v: T)
1144
    where
1145
        T: TryExtractInto<T>
1146
            + TryExtractFrom<Literal>
1147
            + Into<Constant>
1148
            + fmt::Debug
1149
            + Eq
1150
            + Clone
1151
            + 'static,
1152
    {
1153
        let constant: Constant = v.clone().into();
1154
        let v_extracted: T = constant.try_extract_into::<T>().unwrap();
1155
        assert_eq!(v, v_extracted);
1156
    }
1157

1158
    #[test]
1159
    fn unit_roundtrip() {
1160
        test_constant_roundtrip(());
1161
    }
1162

1163
    // test that invalid strings don't error but are instead parsed lossily to match reference impl
1164
    #[test]
1165
    fn parse_invalid_string() {
1166
        let mut bytes = Constant::from(".".to_string())
1167
            .sigma_serialize_bytes()
1168
            .unwrap();
1169
        *bytes.last_mut().unwrap() = 0xf0;
1170
        assert_eq!(
1171
            Constant::sigma_parse_bytes(&bytes).unwrap().v,
1172
            Literal::String("�".into())
1173
        );
1174
    }
1175

1176
    proptest! {
1177

1178
        #![proptest_config(ProptestConfig::with_cases(8))]
1179

1180
        #[test]
1181
        fn bool_roundtrip(v in any::<bool>()) {
1182
            test_constant_roundtrip(v);
1183
        }
1184

1185
        #[test]
1186
        fn i8_roundtrip(v in any::<i8>()) {
1187
            test_constant_roundtrip(v);
1188
        }
1189

1190
        #[test]
1191
        fn i16_roundtrip(v in any::<i16>()) {
1192
            test_constant_roundtrip(v);
1193
        }
1194

1195
        #[test]
1196
        fn i32_roundtrip(v in any::<i32>()) {
1197
            test_constant_roundtrip(v);
1198
        }
1199

1200
        #[test]
1201
        fn i64_roundtrip(v in any::<i64>()) {
1202
            test_constant_roundtrip(v);
1203
        }
1204

1205
        #[test]
1206
        fn bigint_roundtrip(raw in any::<i64>()) {
1207
            let v = BigInt256::from(raw);
1208
            test_constant_roundtrip(v);
1209
        }
1210

1211
        #[test]
1212
        fn group_element_roundtrip(v in any::<EcPoint>()) {
1213
            test_constant_roundtrip(v);
1214
        }
1215

1216
        #[test]
1217
        fn sigma_prop_roundtrip(v in any::<SigmaProp>()) {
1218
            test_constant_roundtrip(v);
1219
        }
1220

1221
        #[test]
1222
        fn vec_i8_roundtrip(v in any::<Vec<i8>>()) {
1223
            test_constant_roundtrip(v);
1224
        }
1225

1226
        #[test]
1227
        fn vec_u8_roundtrip(v in any::<Vec<u8>>()) {
1228
            // eprintln!("{:?}", Constant::from(v.clone()));
1229
            test_constant_roundtrip(v);
1230
        }
1231

1232
        #[test]
1233
        fn token_id_roundtrip(v in any::<TokenId>()) {
1234
            // eprintln!("{:?}", Constant::from(v.clone()));
1235
            test_constant_roundtrip(v);
1236
        }
1237

1238
        #[test]
1239
        fn digest32_roundtrip(v in any::<Digest32>()) {
1240
            test_constant_roundtrip(v);
1241
        }
1242

1243

1244
        #[test]
1245
        fn vec_i16_roundtrip(v in any::<Vec<i16>>()) {
1246
            test_constant_roundtrip(v);
1247
        }
1248

1249
        #[test]
1250
        fn vec_i32_roundtrip(v in any::<Vec<i32>>()) {
1251
            test_constant_roundtrip(v);
1252
        }
1253

1254
        #[test]
1255
        fn vec_i64_roundtrip(v in any::<Vec<i64>>()) {
1256
            // eprintln!("{:?}", Constant::from(v.clone()));
1257
            test_constant_roundtrip(v);
1258
        }
1259

1260
        #[test]
1261
        fn vec_bigint_roundtrip(raw in any::<Vec<i64>>()) {
1262
            let v: Vec<BigInt256> = raw.into_iter().map(BigInt256::from).collect();
1263
            // eprintln!("{:?}", Constant::from(v.clone()));
1264
            test_constant_roundtrip(v);
1265
        }
1266

1267
        #[test]
1268
        fn vec_option_bigint_roundtrip(raw in any::<Vec<i64>>()) {
1269
            let v: Vec<Option<BigInt256>> = raw.into_iter().map(|i| Some(BigInt256::from(i))).collect();
1270
            // eprintln!("{:?}", Constant::from(v.clone()));
1271
            test_constant_roundtrip(v);
1272
        }
1273

1274
        #[test]
1275
        fn vec_sigmaprop_roundtrip(v in any::<Vec<SigmaProp>>()) {
1276
            test_constant_roundtrip(v);
1277
        }
1278

1279
        #[test]
1280
        fn option_primitive_type_roundtrip(v in any::<Option<i64>>()) {
1281
            test_constant_roundtrip(v);
1282
        }
1283

1284
        #[test]
1285
        fn option_nested_vector_type_roundtrip(v in any::<Option<Vec<(i64, bool)>>>()) {
1286
            // eprintln!("{:?}", Constant::from(v.clone()));
1287
            test_constant_roundtrip(v);
1288
        }
1289

1290
        #[test]
1291
        fn option_nested_tuple_type_roundtrip(v in any::<Option<(i64, bool)>>()) {
1292
            test_constant_roundtrip(v);
1293
        }
1294

1295

1296
        #[test]
1297
        fn tuple_primitive_types_roundtrip(v in any::<(i64, bool)>()) {
1298
            // let constant: Constant = v.into();
1299
            // eprintln!("{:?}", constant);
1300
            test_constant_roundtrip(v);
1301
        }
1302

1303
        #[test]
1304
        fn tuple_nested_types_roundtrip(v in any::<(Option<i64>, Vec<SigmaProp>)>()) {
1305
            test_constant_roundtrip(v);
1306
        }
1307

1308
        #[test]
1309
        fn string_roundtrip(v in any::<String>()) {
1310
            test_constant_roundtrip(v);
1311
        }
1312

1313
    }
1314
}
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