Skip to content

Commit a957f7f

Browse files
committed
Add a buffer when writing
As we did when writing in the `segwit` module; add a buffer to cache characters and do writes a buffer at a time. Although we do know the maximum length of the string we are encoding, and we enforce this limit using `encoded_length::<Ck>()` we use an unrelated fixed buffer size and loop over it as many times as needed. This is because, surprisingly the following is not valid Rust `let mut buf = [0_u8, Ck::CODE_LENGTH];` We use a buffer of length 1024 which is larger than the 1023 code length of the two `Checksum` implementations we provide with this crate (`Bech32` and `Bech32m`).
1 parent 63246ad commit a957f7f

File tree

1 file changed

+63
-4
lines changed

1 file changed

+63
-4
lines changed

src/lib.rs

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,12 @@ pub use {
168168
crate::primitives::{Bech32, Bech32m, NoChecksum},
169169
};
170170

171+
// Write to fmt buffer, small during testing to exercise full code path.
172+
#[cfg(not(test))]
173+
const BUF_LENGTH: usize = 1024;
174+
#[cfg(test)]
175+
const BUF_LENGTH: usize = 10;
176+
171177
/// Decodes a bech32 encoded string.
172178
///
173179
/// If this function succeeds the input string was found to be well formed (hrp, separator, bech32
@@ -276,11 +282,26 @@ pub fn encode_lower_to_fmt<Ck: Checksum, W: fmt::Write>(
276282
) -> Result<(), EncodeError> {
277283
let _ = encoded_length::<Ck>(hrp, data)?;
278284

285+
let mut buf = [0u8; BUF_LENGTH];
286+
let mut pos = 0;
287+
279288
let iter = data.iter().copied().bytes_to_fes();
280289
let chars = iter.with_checksum::<Ck>(&hrp).chars();
290+
281291
for c in chars {
282-
fmt.write_char(c)?;
292+
buf[pos] = c as u8;
293+
pos += 1;
294+
295+
if pos == BUF_LENGTH {
296+
let s = core::str::from_utf8(&buf).expect("we only write ASCII");
297+
fmt.write_str(s)?;
298+
pos = 0;
299+
}
283300
}
301+
302+
let s = core::str::from_utf8(&buf[..pos]).expect("we only write ASCII");
303+
fmt.write_str(s)?;
304+
284305
Ok(())
285306
}
286307

@@ -296,11 +317,25 @@ pub fn encode_upper_to_fmt<Ck: Checksum, W: fmt::Write>(
296317
) -> Result<(), EncodeError> {
297318
let _ = encoded_length::<Ck>(hrp, data)?;
298319

320+
let mut buf = [0u8; BUF_LENGTH];
321+
let mut pos = 0;
322+
299323
let iter = data.iter().copied().bytes_to_fes();
300324
let chars = iter.with_checksum::<Ck>(&hrp).chars();
325+
301326
for c in chars {
302-
fmt.write_char(c.to_ascii_uppercase())?;
327+
buf[pos] = c.to_ascii_uppercase() as u8;
328+
pos += 1;
329+
if pos == BUF_LENGTH {
330+
let s = core::str::from_utf8(&buf).expect("we only write ASCII");
331+
fmt.write_str(s)?;
332+
pos = 0;
333+
}
303334
}
335+
336+
let s = core::str::from_utf8(&buf[..pos]).expect("we only write ASCII");
337+
fmt.write_str(s)?;
338+
304339
Ok(())
305340
}
306341

@@ -331,11 +366,23 @@ pub fn encode_lower_to_writer<Ck: Checksum, W: std::io::Write>(
331366
) -> Result<(), EncodeIoError> {
332367
let _ = encoded_length::<Ck>(hrp, data)?;
333368

369+
let mut buf = [0u8; BUF_LENGTH];
370+
let mut pos = 0;
371+
334372
let iter = data.iter().copied().bytes_to_fes();
335373
let chars = iter.with_checksum::<Ck>(&hrp).chars();
374+
336375
for c in chars {
337-
w.write_all(&[c as u8])?;
376+
buf[pos] = c as u8;
377+
pos += 1;
378+
if pos == BUF_LENGTH {
379+
w.write_all(&buf)?;
380+
pos = 0;
381+
}
338382
}
383+
384+
w.write_all(&buf[..pos])?;
385+
339386
Ok(())
340387
}
341388

@@ -352,11 +399,23 @@ pub fn encode_upper_to_writer<Ck: Checksum, W: std::io::Write>(
352399
) -> Result<(), EncodeIoError> {
353400
let _ = encoded_length::<Ck>(hrp, data)?;
354401

402+
let mut buf = [0u8; BUF_LENGTH];
403+
let mut pos = 0;
404+
355405
let iter = data.iter().copied().bytes_to_fes();
356406
let chars = iter.with_checksum::<Ck>(&hrp).chars();
407+
357408
for c in chars {
358-
w.write_all(&[c.to_ascii_uppercase() as u8])?;
409+
buf[pos] = c.to_ascii_uppercase() as u8;
410+
pos += 1;
411+
if pos == BUF_LENGTH {
412+
w.write_all(&buf)?;
413+
pos = 0;
414+
}
359415
}
416+
417+
w.write_all(&buf[..pos])?;
418+
360419
Ok(())
361420
}
362421

0 commit comments

Comments
 (0)