plutus_ledger_api/
aux.rs

1use std::{
2    collections::BTreeMap,
3    iter::{empty, once},
4    str::FromStr,
5};
6
7use nom::{
8    branch::alt,
9    character::complete::{char, digit1},
10    combinator::{map_res, opt, recognize},
11    error::VerboseError,
12    multi::many1,
13    sequence::tuple,
14    IResult,
15};
16use num_bigint::BigInt;
17
18use crate::error::ConversionError;
19
20/// Create a container C from one element.
21pub fn singleton<T, C>(value: T) -> C
22where
23    C: FromIterator<T>,
24{
25    once(value).collect()
26}
27
28/// Create an empty container.
29pub fn none<T, C>() -> C
30where
31    C: FromIterator<T>,
32{
33    empty::<T>().collect()
34}
35
36/// Union two BTreeMaps, call f to resolve conflicts if duplicate keys are encountered.
37pub fn union_btree_maps_with<K: Clone + Ord, V: Clone, F: Fn(V, V) -> V>(
38    f: F,
39    l: BTreeMap<K, V>,
40    r: BTreeMap<K, V>,
41) -> BTreeMap<K, V> {
42    r.into_iter().fold(l.clone(), |mut acc, (k, vr)| {
43        let v = if let Some((_, vl)) = acc.remove_entry(&k) {
44            f(vl, vr)
45        } else {
46            vr
47        };
48        acc.insert(k, v);
49        acc
50    })
51}
52
53pub fn union_b_tree_maps_with<const N: usize, K: Clone + Ord, V: Clone, F: Fn(&V, &V) -> V>(
54    f: F,
55    maps: [&BTreeMap<K, V>; N],
56) -> BTreeMap<K, V> {
57    maps.into_iter().fold(BTreeMap::new(), |acc, m| {
58        m.iter().fold(acc, |mut acc, (k, v)| {
59            acc.entry(k.clone())
60                .and_modify(|va: &mut V| *va = f(va, v))
61                .or_insert(v.clone());
62
63            acc
64        })
65    })
66}
67
68/// Verify that a given bytestring has the expected length
69pub(crate) fn guard_bytes(
70    ctx: &str,
71    bytes: Vec<u8>,
72    expected: usize,
73) -> Result<Vec<u8>, ConversionError> {
74    if bytes.len() == expected {
75        Ok(bytes)
76    } else {
77        Err(ConversionError::invalid_bytestring_length(
78            ctx, expected, "equal to", &bytes,
79        ))
80    }
81}
82
83/// Nom parser for BigInt
84/// Expects an arbitrary length decimal integer, optionally signed
85pub(crate) fn big_int(i: &str) -> IResult<&str, BigInt, VerboseError<&str>> {
86    map_res(
87        recognize(tuple((opt(alt((char('-'), char('+')))), many1(digit1)))),
88        |s: &str| BigInt::from_str(s),
89    )(i)
90}