Skip to content

Commit 8040102

Browse files
committed
feat(io): stop_and_flush() and checked_discard()
1 parent f3aa689 commit 8040102

File tree

7 files changed

+67
-25
lines changed

7 files changed

+67
-25
lines changed

Cargo.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ categories = ["encoding"]
1212
license-file = "LICENSE.txt"
1313

1414
[workspace.dependencies]
15-
tlbits = { path = "./crates/bits", version = "0.6.4" }
16-
tlb = { path = "./crates/tlb", version = "0.6.4" }
17-
tlb-ton = { path = "./crates/tlb-ton", version = "0.6.4" }
18-
ton-contracts = { path = "./crates/contracts", version = "0.6.4" }
19-
toner = { path = "./crates/toner", version = "0.6.4" }
15+
tlbits = { path = "./crates/bits", version = "0.7.0" }
16+
tlb = { path = "./crates/tlb", version = "0.7.0" }
17+
tlb-ton = { path = "./crates/tlb-ton", version = "0.7.0" }
18+
ton-contracts = { path = "./crates/contracts", version = "0.7.0" }
19+
toner = { path = "./crates/toner", version = "0.7.0" }
2020

2121
anyhow = "1"
2222
arbitrary = "1.4"

crates/bits/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "tlbits"
3-
version = "0.6.4"
3+
version = "0.7.0"
44
edition.workspace = true
55
rust-version.workspace = true
66
repository.workspace = true

crates/bits/src/adapters/io.rs

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{
22
fmt::Display,
3-
io::{self, Read, Write},
3+
io::{self, ErrorKind, Read, Write},
44
mem,
55
};
66

@@ -23,16 +23,17 @@ type Buffer = BitArray<[u8; 1], Msb0>;
2323
/// # fn main() -> Result<(), io::Error> {
2424
/// // pack
2525
/// let mut writer = Io::new(Vec::<u8>::new());
26-
/// writer.pack_as::<u8, NBits<7>>(123, ())?
26+
/// writer
27+
/// .pack_as::<u8, NBits<7>>(123, ())?
2728
/// .pack(true, ())?;
28-
/// let buf = writer.into_inner().unwrap();
29+
/// let buf = writer.stop_and_flush().unwrap();
2930
///
3031
/// // unpack
3132
/// let mut reader = Io::new(buf.as_slice());
3233
/// let value1 = reader.unpack_as::<u8, NBits<7>>(())?;
3334
/// let value2 = reader.unpack::<bool>(())?;
34-
///
35-
/// # assert!(reader.buffered().is_empty());
35+
/// let buf = reader.checked_discard().unwrap();
36+
/// assert!(buf.is_empty());
3637
/// # assert_eq!(value1, 123);
3738
/// # assert_eq!(value2, true);
3839
/// # Ok(())
@@ -109,21 +110,42 @@ impl<T> Io<T> {
109110
}
110111
}
111112

113+
impl<R> Io<R>
114+
where
115+
R: Read,
116+
{
117+
/// Safely discards the underlying reader: if any buffered and not-yet-consumed
118+
/// bits left, then checks that it was a stop-bit followed by zeros. Otherwise,
119+
/// returns an error.
120+
///
121+
/// Returns total number of buffered bits discarded.
122+
pub fn checked_discard(self) -> Result<R, io::Error> {
123+
// check if some not yet comsumed bits left
124+
if let Some((stop, rest)) = self.buffered().split_first() {
125+
// check that it's only a stop-bit followed by zeros
126+
if !*stop || rest.any() {
127+
return Err(io::Error::new(ErrorKind::InvalidData, "not all bits read"));
128+
}
129+
}
130+
Ok(self.into_inner_unchecked())
131+
}
132+
}
133+
112134
impl<W> Io<W>
113135
where
114136
W: Write,
115137
{
116-
pub fn fill_up_buffer_and_flush(
117-
&mut self,
118-
fill_bit: bool,
119-
) -> Result<usize, <Self as BitWriter>::Error> {
120-
Ok(if !self.buffered().is_empty() {
138+
/// Finalizes the writer: if any buffered and not-yet-flushed bits left,
139+
/// then writes a stop-bit, fills up the rest by zeros and flushes the buffer.
140+
///
141+
/// Returns total number of additional bits written.
142+
pub fn stop_and_flush(mut self) -> Result<W, io::Error> {
143+
if !self.buffered().is_empty() {
144+
self.write_bit(true)?; // put stop-bit
121145
let n = self.buffer_capacity_left();
122-
self.repeat_bit(n, fill_bit)?;
123-
n
124-
} else {
125-
0
126-
})
146+
self.repeat_bit(n, false)?; // fill the rest with zeros
147+
}
148+
Ok(self.into_inner_unchecked())
127149
}
128150
}
129151

@@ -268,6 +290,26 @@ where
268290
}
269291
Ok(())
270292
}
293+
294+
fn repeat_bit(&mut self, mut n: usize, bit: bool) -> Result<(), Self::Error> {
295+
while n > 0 && !self.buffered().is_empty() {
296+
self.write_bit(bit)?;
297+
n -= 1;
298+
}
299+
300+
n -= io::copy(
301+
&mut io::repeat(if bit { !0 } else { 0 }).take((n / bits_of::<u8>()) as u64),
302+
&mut self.io,
303+
)? as usize
304+
* bits_of::<u8>();
305+
306+
while n > 0 {
307+
self.write_bit(bit)?;
308+
n -= 1;
309+
}
310+
311+
Ok(())
312+
}
271313
}
272314

273315
impl Error for io::Error {

crates/contracts/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ton-contracts"
3-
version = "0.6.4"
3+
version = "0.7.0"
44
edition.workspace = true
55
rust-version.workspace = true
66
repository.workspace = true

crates/tlb-ton/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "tlb-ton"
3-
version = "0.6.4"
3+
version = "0.7.0"
44
edition.workspace = true
55
rust-version.workspace = true
66
repository.workspace = true

crates/tlb/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "tlb"
3-
version = "0.6.4"
3+
version = "0.7.0"
44
edition.workspace = true
55
rust-version.workspace = true
66
repository.workspace = true

crates/toner/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "toner"
3-
version = "0.6.4"
3+
version = "0.7.0"
44
edition.workspace = true
55
rust-version.workspace = true
66
repository.workspace = true

0 commit comments

Comments
 (0)