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

ergoplatform / sigma-rust / 8953175335

04 May 2024 08:51PM UTC coverage: 80.473% (+0.1%) from 80.331%
8953175335

Pull #736

github

web-flow
Merge 0fdf2d258 into 57a105462
Pull Request #736: Transaction Validation

165 of 228 new or added lines in 15 files covered. (72.37%)

8 existing lines in 2 files now uncovered.

10723 of 13325 relevant lines covered (80.47%)

3.29 hits per line

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

56.84
/ergotree-ir/src/mir/value.rs
1
//! Ergo data type
2

3
use std::convert::TryInto;
4
use std::fmt::Formatter;
5
use std::sync::Arc;
6

7
use impl_trait_for_tuples::impl_for_tuples;
8
use sigma_util::AsVecI8;
9

10
use crate::bigint256::BigInt256;
11
use crate::chain::ergo_box::ErgoBox;
12
use crate::sigma_protocol::sigma_boolean::SigmaProp;
13
use crate::types::stuple::TupleItems;
14
use crate::types::stype::LiftIntoSType;
15
use crate::types::stype::SType;
16
use ergo_chain_types::{EcPoint, Header, PreHeader};
17

18
use super::avl_tree_data::AvlTreeData;
19
use super::constant::Literal;
20
use super::constant::TryExtractFrom;
21
use super::constant::TryExtractFromError;
22
use super::constant::TryExtractInto;
23
use super::expr::Expr;
24
use super::func_value::FuncArg;
25

26
extern crate derive_more;
27
use derive_more::From;
28

29
#[derive(PartialEq, Eq, Debug, Clone)]
30
/// Collection for primitive values (i.e byte array)
31
pub enum NativeColl {
32
    /// Collection of bytes
33
    CollByte(Vec<i8>),
34
}
35

36
impl NativeColl {
37
    /// Collection element type
38
    pub fn elem_tpe(&self) -> &SType {
×
39
        match self {
40
            NativeColl::CollByte(_) => &SType::SByte,
41
        }
42
    }
43
}
44

45
/// Collection elements
46
#[derive(PartialEq, Eq, Debug, Clone)]
47
pub enum CollKind<T> {
48
    /// Collection elements stored as a vector of Rust values
49
    NativeColl(NativeColl),
50
    /// Collection elements stored as a vector of Value's
51
    WrappedColl {
52
        /// Collection element type
53
        elem_tpe: SType,
54
        /// Collection elements
55
        items: Vec<T>,
56
    },
57
}
58

59
impl<T> CollKind<T>
60
where
61
    T: PartialEq + Eq + Clone,
62
    T: From<i8>,
63
    i8: TryExtractFrom<T>,
64
    Vec<i8>: TryExtractFrom<T>,
65
    Vec<T>: TryExtractFrom<T>,
66
{
67
    /// Build a collection from items, storing them as Rust types values when neccessary
68
    pub fn from_vec(elem_tpe: SType, items: Vec<T>) -> Result<CollKind<T>, TryExtractFromError> {
5✔
69
        match elem_tpe {
5✔
70
            SType::SByte => items
4✔
71
                .into_iter()
72
                .map(|v| v.try_extract_into::<i8>())
4✔
73
                .collect::<Result<Vec<_>, _>>()
74
                .map(|bytes| CollKind::NativeColl(NativeColl::CollByte(bytes))),
4✔
75
            _ => Ok(CollKind::WrappedColl { elem_tpe, items }),
5✔
76
        }
77
    }
78

79
    /// Build a collection from items where each is a collection as well, flattening the arrays
80
    /// This will convert a Coll[Coll\[T\]] to a Coll\[T\]
81
    pub fn from_vec_vec(
1✔
82
        elem_tpe: SType,
83
        items: Vec<T>,
84
    ) -> Result<CollKind<T>, TryExtractFromError> {
85
        match elem_tpe {
1✔
86
            SType::SColl(inner_type) if matches!(&*inner_type, SType::SByte) => items
1✔
87
                .into_iter()
88
                .map(|v| v.try_extract_into::<Vec<i8>>())
×
89
                .collect::<Result<Vec<_>, _>>()
90
                .map(|bytes| CollKind::NativeColl(NativeColl::CollByte(bytes.concat()))),
×
91
            SType::SColl(flat_type) => items
3✔
92
                .into_iter()
93
                .map(|v| v.try_extract_into::<Vec<T>>())
2✔
94
                .collect::<Result<Vec<_>, _>>()
95
                .map(|v| CollKind::WrappedColl {
3✔
96
                    elem_tpe: *flat_type,
1✔
97
                    items: v.concat(),
2✔
98
                }),
NEW
99
            _ => Err(TryExtractFromError(format!(
×
NEW
100
                "Expected Value::Coll, got: {:?}",
×
NEW
101
                elem_tpe
×
102
            ))),
103
        }
104
    }
105

106
    /// Collection element type
107
    pub fn elem_tpe(&self) -> &SType {
1✔
108
        match self {
2✔
109
            CollKind::NativeColl(ncoll) => match ncoll {
1✔
110
                NativeColl::CollByte(_) => &SType::SByte,
1✔
111
            },
112
            CollKind::WrappedColl { elem_tpe, .. } => elem_tpe,
1✔
113
        }
114
    }
115

116
    /// Return items, as vector of Values
117
    pub fn as_vec(&self) -> Vec<T> {
4✔
118
        match self {
4✔
119
            CollKind::NativeColl(NativeColl::CollByte(coll_byte)) => coll_byte
2✔
120
                .clone()
121
                .into_iter()
122
                .map(|byte| byte.into())
4✔
123
                .collect(),
124
            CollKind::WrappedColl {
4✔
125
                elem_tpe: _,
×
126
                items: v,
×
127
            } => v.clone(),
×
128
        }
129
    }
130
}
131

132
/// Lambda
133
#[derive(PartialEq, Eq, Debug, Clone)]
134
pub struct Lambda {
135
    /// Argument placeholders
136
    pub args: Vec<FuncArg>,
137
    /// Body
138
    pub body: Box<Expr>,
139
}
140

141
/// Runtime value
142
#[derive(PartialEq, Eq, Debug, Clone, From)]
143
pub enum Value {
144
    /// Boolean
145
    Boolean(bool),
146
    /// Byte
147
    Byte(i8),
148
    /// Short
149
    Short(i16),
150
    /// Int
151
    Int(i32),
152
    /// Long
153
    Long(i64),
154
    /// Unit struct
155
    Unit,
156
    /// Big integer
157
    BigInt(BigInt256),
158
    /// GroupElement
159
    GroupElement(Box<EcPoint>),
160
    /// Sigma property
161
    SigmaProp(Box<SigmaProp>),
162
    /// Ergo box
163
    CBox(Arc<ErgoBox>),
164
    /// AVL tree
165
    AvlTree(Box<AvlTreeData>),
166
    /// Collection of values of the same type
167
    Coll(CollKind<Value>),
168
    /// Tuple (arbitrary type values)
169
    Tup(TupleItems<Value>),
170
    /// Transaction(and blockchain) context info
171
    Context,
172
    /// Block header
173
    Header(Box<Header>),
174
    /// Header with predictable data
175
    PreHeader(Box<PreHeader>),
176
    /// Global which is used to define global methods
177
    Global,
178
    /// Optional value
179
    Opt(Box<Option<Value>>),
180
    /// lambda
181
    Lambda(Lambda),
182
}
183

184
impl Value {
185
    /// Create Sigma property constant
186
    pub fn sigma_prop(prop: SigmaProp) -> Value {
×
187
        Value::SigmaProp(Box::new(prop))
×
188
    }
189
}
190

191
impl<T: Into<SigmaProp>> From<T> for Value {
192
    fn from(t: T) -> Self {
1✔
193
        Value::SigmaProp(Box::new(t.into()))
2✔
194
    }
195
}
196

197
impl From<EcPoint> for Value {
198
    fn from(v: EcPoint) -> Self {
1✔
199
        Value::GroupElement(Box::new(v))
1✔
200
    }
201
}
202

203
impl From<Vec<i8>> for Value {
204
    fn from(v: Vec<i8>) -> Self {
2✔
205
        Value::Coll(CollKind::NativeColl(NativeColl::CollByte(v)))
2✔
206
    }
207
}
208

209
impl From<Vec<u8>> for Value {
210
    fn from(v: Vec<u8>) -> Self {
2✔
211
        Value::Coll(CollKind::NativeColl(NativeColl::CollByte(v.as_vec_i8())))
4✔
212
    }
213
}
214

215
impl<T: Into<Value>> From<Option<T>> for Value {
216
    fn from(opt: Option<T>) -> Self {
1✔
217
        Value::Opt(Box::new(opt.map(|v| v.into())))
3✔
218
    }
219
}
220

221
impl From<Literal> for Value {
222
    fn from(lit: Literal) -> Self {
4✔
223
        match lit {
5✔
224
            Literal::Boolean(b) => Value::Boolean(b),
2✔
225
            Literal::Byte(b) => Value::Byte(b),
1✔
226
            Literal::Short(s) => Value::Short(s),
1✔
227
            Literal::Int(i) => Value::Int(i),
3✔
228
            Literal::Long(l) => Value::Long(l),
1✔
229
            Literal::BigInt(b) => Value::BigInt(b),
1✔
230
            Literal::Unit => Value::Unit,
×
231
            Literal::SigmaProp(s) => Value::SigmaProp(s),
4✔
232
            Literal::GroupElement(e) => Value::GroupElement(e),
1✔
233
            Literal::CBox(b) => Value::CBox(b),
×
234
            Literal::Coll(coll) => {
3✔
235
                let converted_coll = match coll {
3✔
236
                    CollKind::NativeColl(n) => CollKind::NativeColl(n),
2✔
237
                    CollKind::WrappedColl { elem_tpe, items } => CollKind::WrappedColl {
238
                        elem_tpe,
239
                        items: items.into_iter().map(Value::from).collect(),
6✔
240
                    },
241
                };
242
                Value::Coll(converted_coll)
3✔
243
            }
244
            Literal::AvlTree(a) => Value::AvlTree(a),
1✔
245
            Literal::Opt(lit) => Value::Opt(Box::new(lit.into_iter().next().map(Value::from))),
4✔
246
            Literal::Tup(t) => Value::Tup(t.mapped(Value::from)),
1✔
247
        }
248
    }
249
}
250

251
impl std::fmt::Display for Value {
252
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1✔
253
        match self {
1✔
254
            Value::Coll(CollKind::NativeColl(NativeColl::CollByte(i8_bytes))) => {
×
255
                write!(f, "Coll[Byte](")?;
×
256
                for (i, b) in i8_bytes.iter().enumerate() {
×
257
                    if i > 0 {
×
258
                        write!(f, ", ")?;
×
259
                    }
260
                    write!(f, "{}", b)?;
×
261
                }
262
                write!(f, ")")
×
263
            }
264
            Value::Coll(CollKind::WrappedColl { elem_tpe, items }) => {
×
265
                write!(f, "Coll[{}](", elem_tpe)?;
×
266
                for (i, item) in items.iter().enumerate() {
×
267
                    if i > 0 {
×
268
                        write!(f, ", ")?;
×
269
                    }
270
                    item.fmt(f)?;
×
271
                }
272
                write!(f, ")")
×
273
            }
274
            Value::Opt(boxed_opt) => {
×
275
                if let Some(v) = &**boxed_opt {
×
276
                    write!(f, "Some(")?;
×
277
                    v.fmt(f)?;
×
278
                    write!(f, ")")
×
279
                } else {
280
                    write!(f, "None")
×
281
                }
282
            }
283
            Value::Tup(items) => {
×
284
                write!(f, "(")?;
×
285
                for (i, item) in items.iter().enumerate() {
×
286
                    if i > 0 {
×
287
                        write!(f, ", ")?;
×
288
                    }
289
                    item.fmt(f)?;
1✔
290
                }
291
                write!(f, ")")
×
292
            }
293
            Value::Unit => write!(f, "()"),
×
294
            Value::Boolean(v) => v.fmt(f),
×
295
            Value::Byte(v) => v.fmt(f),
×
296
            Value::Short(v) => v.fmt(f),
×
297
            Value::Int(v) => v.fmt(f),
1✔
298
            Value::Long(v) => write!(f, "{}L", v),
×
299
            Value::BigInt(v) => v.fmt(f),
×
300
            Value::SigmaProp(v) => v.fmt(f),
×
301
            Value::GroupElement(v) => v.fmt(f),
×
302
            Value::AvlTree(v) => write!(f, "AvlTree({:?})", v),
×
303
            Value::CBox(v) => write!(f, "ErgoBox({:?})", v),
×
304
            Value::Context => write!(f, "CONTEXT"),
×
305
            Value::Header(_) => write!(f, "HEADER"),
×
306
            Value::PreHeader(_) => write!(f, "PREHEADER"),
×
307
            Value::Global => write!(f, "GLOBAL"),
×
308
            Value::Lambda(v) => write!(f, "{v:?}"),
×
309
        }
310
    }
311
}
312

313
/// Marker trait to select types which stored as Vec of wrapped Value's
314
pub trait StoreWrapped {}
315

316
impl StoreWrapped for bool {}
317
impl StoreWrapped for i16 {}
318
impl StoreWrapped for i32 {}
319
impl StoreWrapped for i64 {}
320
impl StoreWrapped for BigInt256 {}
321
impl StoreWrapped for Header {}
322
impl StoreWrapped for Arc<ErgoBox> {}
323
impl StoreWrapped for EcPoint {}
324
impl StoreWrapped for SigmaProp {}
325
impl<T: StoreWrapped> StoreWrapped for Option<T> {}
326
impl<T> StoreWrapped for Vec<T> {}
327
impl StoreWrapped for Value {}
328
impl StoreWrapped for Literal {}
329

330
#[impl_for_tuples(2, 4)]
331
impl StoreWrapped for Tuple {}
332

333
impl<T: LiftIntoSType + StoreWrapped + Into<Value>> From<Vec<T>> for Value {
334
    fn from(v: Vec<T>) -> Self {
2✔
335
        Value::Coll(CollKind::WrappedColl {
4✔
336
            elem_tpe: T::stype(),
2✔
337
            items: v.into_iter().map(|i| i.into()).collect(),
8✔
338
        })
339
    }
340
}
341

342
#[allow(clippy::from_over_into)]
343
#[allow(clippy::unwrap_used)]
344
#[impl_for_tuples(2, 4)]
345
impl Into<Value> for Tuple {
346
    fn into(self) -> Value {
2✔
347
        let v: Vec<Value> = [for_tuples!(  #( Tuple.into() ),* )].to_vec();
2✔
348
        Value::Tup(v.try_into().unwrap())
2✔
349
    }
350
}
351

352
impl From<Vec<Arc<ErgoBox>>> for Value {
353
    fn from(v: Vec<Arc<ErgoBox>>) -> Self {
1✔
354
        Value::Coll(CollKind::WrappedColl {
1✔
355
            elem_tpe: SType::SBox,
1✔
356
            items: v.into_iter().map(|i| i.into()).collect(),
4✔
357
        })
358
    }
359
}
360

361
impl TryExtractFrom<Value> for bool {
362
    fn try_extract_from(cv: Value) -> Result<bool, TryExtractFromError> {
1✔
363
        match cv {
1✔
364
            Value::Boolean(v) => Ok(v),
1✔
365
            _ => Err(TryExtractFromError(format!(
×
366
                "expected bool, found {:?}",
367
                cv
368
            ))),
369
        }
370
    }
371
}
372

373
impl TryExtractFrom<Value> for i8 {
374
    fn try_extract_from(cv: Value) -> Result<i8, TryExtractFromError> {
2✔
375
        match cv {
2✔
376
            Value::Byte(v) => Ok(v),
2✔
377
            _ => Err(TryExtractFromError(format!("expected i8, found {:?}", cv))),
×
378
        }
379
    }
380
}
381

382
impl TryExtractFrom<Value> for i16 {
383
    fn try_extract_from(cv: Value) -> Result<i16, TryExtractFromError> {
1✔
384
        match cv {
1✔
385
            Value::Short(v) => Ok(v),
1✔
386
            _ => Err(TryExtractFromError(format!("expected i16, found {:?}", cv))),
×
387
        }
388
    }
389
}
390

391
impl TryExtractFrom<Value> for i32 {
392
    fn try_extract_from(cv: Value) -> Result<i32, TryExtractFromError> {
3✔
393
        match cv {
3✔
394
            Value::Int(v) => Ok(v),
3✔
395
            _ => Err(TryExtractFromError(format!("expected i32, found {:?}", cv))),
×
396
        }
397
    }
398
}
399

400
impl TryExtractFrom<Value> for i64 {
401
    fn try_extract_from(cv: Value) -> Result<i64, TryExtractFromError> {
1✔
402
        match cv {
1✔
403
            Value::Long(v) => Ok(v),
1✔
404
            _ => Err(TryExtractFromError(format!("expected i64, found {:?}", cv))),
×
405
        }
406
    }
407
}
408

409
impl TryExtractFrom<Value> for EcPoint {
410
    fn try_extract_from(cv: Value) -> Result<EcPoint, TryExtractFromError> {
1✔
411
        match cv {
1✔
412
            Value::GroupElement(v) => Ok(*v),
2✔
413
            _ => Err(TryExtractFromError(format!(
×
414
                "expected EcPoint, found {:?}",
415
                cv
416
            ))),
417
        }
418
    }
419
}
420

421
impl TryExtractFrom<Value> for SigmaProp {
422
    fn try_extract_from(cv: Value) -> Result<SigmaProp, TryExtractFromError> {
4✔
423
        match cv {
4✔
424
            Value::SigmaProp(v) => Ok(*v),
12✔
425
            _ => Err(TryExtractFromError(format!(
×
426
                "expected SigmaProp, found {:?}",
427
                cv
428
            ))),
429
        }
430
    }
431
}
432

433
impl TryExtractFrom<Value> for Arc<ErgoBox> {
434
    fn try_extract_from(c: Value) -> Result<Self, TryExtractFromError> {
1✔
435
        match c {
1✔
436
            Value::CBox(b) => Ok(b),
1✔
437
            _ => Err(TryExtractFromError(format!(
×
438
                "expected ErgoBox, found {:?}",
439
                c
440
            ))),
441
        }
442
    }
443
}
444

445
impl TryExtractFrom<Value> for Header {
446
    fn try_extract_from(c: Value) -> Result<Self, TryExtractFromError> {
1✔
447
        match c {
1✔
448
            Value::Header(h) => Ok(*h),
3✔
449
            _ => Err(TryExtractFromError(format!(
1✔
450
                "expected Header, found {:?}",
451
                c
452
            ))),
453
        }
454
    }
455
}
456

457
impl TryExtractFrom<Value> for PreHeader {
458
    fn try_extract_from(c: Value) -> Result<Self, TryExtractFromError> {
1✔
459
        match c {
1✔
460
            Value::PreHeader(ph) => Ok(*ph),
3✔
461
            _ => Err(TryExtractFromError(format!(
1✔
462
                "expected PreHeader, found {:?}",
463
                c
464
            ))),
465
        }
466
    }
467
}
468

469
impl<T: TryExtractFrom<Value> + StoreWrapped> TryExtractFrom<Value> for Vec<T> {
470
    fn try_extract_from(c: Value) -> Result<Self, TryExtractFromError> {
10✔
471
        match c {
10✔
472
            Value::Coll(coll) => match coll {
10✔
473
                CollKind::WrappedColl {
10✔
474
                    elem_tpe: _,
×
475
                    items: v,
×
476
                } => v.into_iter().map(T::try_extract_from).collect(),
×
477
                _ => Err(TryExtractFromError(format!(
×
478
                    "expected {:?}, found {:?}",
×
479
                    std::any::type_name::<Self>(),
×
480
                    coll
×
481
                ))),
482
            },
483
            _ => Err(TryExtractFromError(format!(
×
484
                "expected {:?}, found {:?}",
×
485
                std::any::type_name::<Self>(),
×
486
                c
×
487
            ))),
488
        }
489
    }
490
}
491

492
impl<T: TryExtractFrom<Value> + StoreWrapped, const N: usize> TryExtractFrom<Value> for [T; N] {
493
    fn try_extract_from(c: Value) -> Result<Self, TryExtractFromError> {
1✔
494
        match c {
1✔
495
            Value::Coll(coll) => match coll {
1✔
496
                CollKind::WrappedColl {
1✔
497
                    elem_tpe: _,
×
498
                    items: v,
×
499
                } => {
×
500
                    let v = v
2✔
501
                        .into_iter()
502
                        .map(T::try_extract_from)
×
503
                        .collect::<Result<Vec<_>, _>>()?;
504
                    let len = v.len();
2✔
505
                    v.try_into().map_err(|_| TryExtractFromError(format!("can't convert vec of {:?} with length of {:?} to array with length of {:?}", std::any::type_name::<T>(), len, N)))
1✔
506
                }
507
                _ => Err(TryExtractFromError(format!(
×
508
                    "expected {:?}, found {:?}",
×
509
                    std::any::type_name::<Self>(),
×
510
                    coll
×
511
                ))),
512
            },
513
            _ => Err(TryExtractFromError(format!(
×
514
                "expected {:?}, found {:?}",
×
515
                std::any::type_name::<Self>(),
×
516
                c
×
517
            ))),
518
        }
519
    }
520
}
521

522
impl TryExtractFrom<Value> for Vec<i8> {
523
    fn try_extract_from(v: Value) -> Result<Self, TryExtractFromError> {
1✔
524
        match v {
1✔
525
            Value::Coll(v) => match v {
1✔
526
                CollKind::NativeColl(NativeColl::CollByte(bs)) => Ok(bs),
1✔
527
                _ => Err(TryExtractFromError(format!(
×
528
                    "expected {:?}, found {:?}",
529
                    std::any::type_name::<Self>(),
×
530
                    v
531
                ))),
532
            },
533
            _ => Err(TryExtractFromError(format!(
×
534
                "expected {:?}, found {:?}",
535
                std::any::type_name::<Self>(),
×
536
                v
537
            ))),
538
        }
539
    }
540
}
541

542
impl TryExtractFrom<Value> for Vec<u8> {
543
    fn try_extract_from(v: Value) -> Result<Self, TryExtractFromError> {
1✔
544
        use sigma_util::FromVecI8;
545
        Vec::<i8>::try_extract_from(v).map(Vec::<u8>::from_vec_i8)
1✔
546
    }
547
}
548

549
impl TryExtractFrom<Value> for Value {
550
    fn try_extract_from(v: Value) -> Result<Self, TryExtractFromError> {
1✔
551
        Ok(v)
1✔
552
    }
553
}
554

555
impl TryExtractFrom<Value> for BigInt256 {
556
    fn try_extract_from(v: Value) -> Result<Self, TryExtractFromError> {
1✔
557
        match v {
1✔
558
            Value::BigInt(bi) => Ok(bi),
1✔
559
            _ => Err(TryExtractFromError(format!(
×
560
                "expected {:?}, found {:?}",
561
                std::any::type_name::<Self>(),
×
562
                v
563
            ))),
564
        }
565
    }
566
}
567

568
impl TryExtractFrom<Value> for AvlTreeData {
569
    fn try_extract_from(v: Value) -> Result<Self, TryExtractFromError> {
1✔
570
        match v {
1✔
571
            Value::AvlTree(a) => Ok(*a),
3✔
572
            _ => Err(TryExtractFromError(format!(
×
573
                "expected {:?}, found {:?}",
574
                std::any::type_name::<Self>(),
×
575
                v
576
            ))),
577
        }
578
    }
579
}
580

581
impl<T: TryExtractFrom<Value> + StoreWrapped> TryExtractFrom<Vec<Value>> for Vec<T> {
582
    fn try_extract_from(v: Vec<Value>) -> Result<Self, TryExtractFromError> {
×
583
        v.into_iter().map(|it| it.try_extract_into::<T>()).collect()
×
584
    }
585
}
586

587
// impl TryExtractFrom<Value> for Rc<Context> {
588
//     fn try_extract_from(v: Value) -> Result<Self, TryExtractFromError> {
589
//         match v {
590
//             Value::Context(ctx) => Ok(ctx),
591
//             _ => Err(TryExtractFromError(format!(
592
//                 "expected Context, found {:?}",
593
//                 v
594
//             ))),
595
//         }
596
//     }
597
// }
598

599
impl<T: TryExtractFrom<Value>> TryExtractFrom<Value> for Option<T> {
600
    fn try_extract_from(v: Value) -> Result<Self, TryExtractFromError> {
1✔
601
        match v {
1✔
602
            Value::Opt(opt) => opt.map(T::try_extract_from).transpose(),
3✔
603
            _ => Err(TryExtractFromError(format!(
×
604
                "expected Option, found {:?}",
×
605
                v
×
606
            ))),
607
        }
608
    }
609
}
610

611
#[impl_for_tuples(2, 4)]
612
impl TryExtractFrom<Value> for Tuple {
613
    fn try_extract_from(v: Value) -> Result<Self, TryExtractFromError> {
4✔
614
        match v {
4✔
615
            Value::Tup(items) => {
4✔
616
                let mut iter = items.iter();
8✔
617
                Ok(for_tuples!( ( #(
4✔
618
                                Tuple::try_extract_from(
619
                                    iter
12✔
620
                                        .next()
621
                                        .cloned()
622
                                        .ok_or_else(|| TryExtractFromError("not enough items in STuple".to_string()))?
×
623
                                )?
624
                                ),* ) ))
×
625
            }
626
            _ => Err(TryExtractFromError(format!(
×
627
                "expected Context, found {:?}",
628
                v
629
            ))),
630
        }
631
    }
632
}
633

634
#[cfg(test)]
635
#[cfg(feature = "arbitrary")]
636
#[allow(clippy::unwrap_used)]
637
mod tests {
638
    use super::*;
639

640
    #[test]
641
    fn byte_u8_array_into() {
642
        let bytes = vec![1u8, 2u8, 3u8];
643
        let value: Value = bytes.into();
644
        assert!(matches!(
645
            value,
646
            Value::Coll(CollKind::NativeColl(NativeColl::CollByte(_)))
647
        ))
648
    }
649

650
    #[test]
651
    fn byte_i8_array_into() {
652
        let bytes = vec![1i8, 2i8, 3i8];
653
        let value: Value = bytes.into();
654
        assert!(matches!(
655
            value,
656
            Value::Coll(CollKind::NativeColl(NativeColl::CollByte(_)))
657
        ))
658
    }
659

660
    #[test]
661
    fn byte_from_vec_roundtrip() {
662
        let bytes = vec![1i8, 2i8, 3i8];
663
        let wrapped: Vec<Value> = bytes.into_iter().map(|b| b.into()).collect();
664
        let coll = CollKind::from_vec(SType::SByte, wrapped.clone()).unwrap();
665
        assert!(matches!(
666
            coll,
667
            CollKind::NativeColl(NativeColl::CollByte(_))
668
        ));
669
        let as_vec = coll.as_vec();
670
        assert_eq!(as_vec, wrapped);
671
    }
672

673
    #[test]
674
    fn wrapped_from_vec_roundtrip() {
675
        let longs = vec![1i64, 2i64, 3i64];
676
        let wrapped: Vec<Value> = longs.into_iter().map(|b| b.into()).collect();
677
        let coll = CollKind::from_vec(SType::SLong, wrapped.clone()).unwrap();
678
        assert!(matches!(
679
            coll,
680
            CollKind::WrappedColl {
681
                elem_tpe: SType::SLong,
682
                items: _,
683
            }
684
        ));
685
        let as_vec = coll.as_vec();
686
        assert_eq!(as_vec, wrapped);
687
    }
688
}
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