forked from BlockstreamResearch/rust-simplicity
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathframe.rs
More file actions
132 lines (112 loc) · 4.11 KB
/
Copy pathframe.rs
File metadata and controls
132 lines (112 loc) · 4.11 KB
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// SPDX-License-Identifier: CC0-1.0
//! # Simplicity Frame
//!
//! Implementation of Frames in the Simplicity BitMachine.
//! A frame is a, possibly empty, cell array with a cursor referencing
//! a cell in the array.
use crate::BitIter;
/// Context to access a sub-slice of [`super::exec::BitMachine`]'s data.
/// Read and write operations require a reference to the data,
/// as it is not contained in this struct.
#[derive(Debug, Eq, PartialEq)]
pub(super) struct Frame {
/// Current position of the cursor.
/// For read frames, this is the next bit which is to be read.
/// For write frames, this is the next bit which is to be (over)written.
cursor: usize,
/// Start index of this frame in the referenced data.
start: usize,
/// The total bit length of this frame.
len: usize,
}
impl Frame {
/// Create a new frame that starts at the given index and that is of given length.
pub(super) fn new(start: usize, len: usize) -> Self {
Frame {
cursor: start,
start,
len,
}
}
/// Return the start index of the frame inside the referenced data.
pub(super) fn start(&self) -> usize {
self.start
}
/// Return the bit width of the frame.
pub(super) fn bit_width(&self) -> usize {
self.len
}
/// Makes a copy of the frame.
///
/// This copies *only the indices* and none of the underlying
/// data. It is the caller's responsibility to make sure that
/// the indices are not invalidated.
pub(super) fn shallow_copy(&self) -> Self {
Self {
cursor: self.cursor,
start: self.start,
len: self.len,
}
}
/// Reset the cursor to the start.
pub(super) fn reset_cursor(&mut self) {
self.cursor = self.start;
}
/// Return the current bit.
pub(super) fn peek_bit(&self, data: &[u8]) -> bool {
let (byte_index, bit_index) = get_indices(self.cursor);
data[byte_index] & (1 << (7 - bit_index)) != 0
}
/// Return the current bit and advance the cursor.
pub(super) fn read_bit(&mut self, data: &[u8]) -> bool {
let (byte_index, bit_index) = get_indices(self.cursor);
let bit = data[byte_index] & (1 << (7 - bit_index)) != 0;
self.cursor += 1;
bit
}
/// Write the given value to the current bit and advance the cursor.
pub(super) fn write_bit(&mut self, bit: bool, data: &mut [u8]) {
let (byte_index, bit_index) = get_indices(self.cursor);
let write_mask = 1 << (7 - bit_index);
if bit {
data[byte_index] |= write_mask;
} else {
data[byte_index] &= !write_mask;
}
self.cursor += 1;
}
/// Write a big-endian u8 value and advance the cursor.
pub(super) fn write_u8(&mut self, value: u8, data: &mut [u8]) {
for idx in 0..8 {
self.write_bit(value & (1 << (7 - idx)) != 0, data);
}
}
/// Move the cursor forward by the given length.
pub(super) fn move_cursor_forward(&mut self, len: usize) {
self.cursor += len;
}
/// Move the cursor backward by the given length.
pub(super) fn move_cursor_backward(&mut self, len: usize) {
self.cursor -= len;
}
/// Copy a bit string of given length from another frame into the present one.
pub(super) fn copy_from(&mut self, other: &Self, len: usize, data: &mut [u8]) {
for i in 0..len {
let (other_byte_index, other_bit_index) = get_indices(other.cursor + i);
let bit = data[other_byte_index] & (1 << (7 - other_bit_index)) != 0;
self.write_bit(bit, data);
}
}
/// Return an iterator over the frame's remaining bits, starting at the current cursor position.
pub(super) fn as_bit_iter_from_cursor<'a>(
&self,
data: &'a [u8],
) -> BitIter<core::iter::Copied<core::slice::Iter<'a, u8>>> {
BitIter::byte_slice_window(data, self.cursor, self.start + self.len)
}
}
fn get_indices(cursor: usize) -> (usize, usize) {
let byte_index = cursor / 8;
let bit_index = cursor % 8;
(byte_index, bit_index)
}