1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/// Encodes number to minimimum number of bytes (top-encoding).
///
/// Smaller types need to be converted to u64 before using this function.
///
/// No generics here, we avoid monomorphization to make the SC binary as small as possible.
pub fn top_encode_number(x: u64, signed: bool, buffer: &mut [u8; 8]) -> &[u8] {
    *buffer = x.to_be_bytes();
    if x == 0 {
        // 0 is a special case
        return &[];
    }

    if signed && x == u64::MAX {
        // -1 is a special case
        // will return a single 0xFF byte
        return &buffer[7..];
    }

    let negative = signed &&  // only possible when signed flag
		buffer[0] > 0x7fu8; // most significant bit is 1

    let irrelevant_byte = if negative { 0xffu8 } else { 0x00u8 };

    let mut offset = 0usize;
    while buffer[offset] == irrelevant_byte {
        debug_assert!(offset < 7);
        offset += 1;
    }

    if signed && buffer[offset] >> 7 != negative as u8 {
        debug_assert!(offset > 0);
        offset -= 1;
    }

    &buffer[offset..]
}

/// Handles both top-encoding and nested-encoding, signed and unsigned, of any length.
///
/// The result needs to be validated to not exceed limits and then cast to the desired type.
///
/// No generics here, we avoid monomorphization to make the SC binary as small as possible.
pub fn universal_decode_number(bytes: &[u8], signed: bool) -> u64 {
    if bytes.is_empty() {
        return 0;
    }
    let negative = signed && bytes[0] >> 7 == 1;
    let mut result = if negative {
        // start with all bits set to 1,
        // to ensure that if there are fewer bytes than the result type width,
        // the leading bits will be 1 instead of 0
        u64::MAX
    } else {
        0u64
    };
    for byte in bytes.iter() {
        result <<= 8;
        result |= *byte as u64;
    }
    result
}