Skip to content

Commit 4d20627

Browse files
committed
Optimize length-prefixed writes
1 parent aecb820 commit 4d20627

File tree

2 files changed

+42
-19
lines changed

2 files changed

+42
-19
lines changed

lightning/src/util/ser.rs

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
//! A very simple serialization framework which is used to serialize/deserialize messages as well
1111
//! as ChannelsManagers and ChannelMonitors.
1212
13-
use std::io::{Read, Write};
13+
use std::io::{Read, Write, Cursor};
1414
use std::collections::HashMap;
1515
use std::hash::Hash;
1616
use std::sync::Mutex;
@@ -62,6 +62,25 @@ impl Writer {
6262
pub fn len(&self) -> usize {
6363
self.0.len()
6464
}
65+
66+
/// Insert the length of a data slice before the slice start
67+
pub fn insert_length(&mut self, slice_start: usize, length_adjust: usize) -> Result<(), ::std::io::Error> {
68+
let slice_end = self.len();
69+
let length = slice_end - slice_start + length_adjust;
70+
// Write the length after the slice, to check how many bytes
71+
BigSize(length as u64).write(self)?;
72+
let len_end = self.len();
73+
let len_len = len_end - slice_end;
74+
self.0.resize(slice_end, 0);
75+
// Shift the slice to make space for the length
76+
for _ in 0 .. len_len {
77+
self.0.insert(slice_start, 0);
78+
}
79+
let mut cursor = Cursor::new(&mut self.0);
80+
cursor.set_position(slice_start as u64);
81+
// Write the length again at the right spot
82+
BigSize(length as u64).write_write(&mut cursor)
83+
}
6584
}
6685

6786
impl Write for Writer {
@@ -225,28 +244,34 @@ impl Readable for U48 {
225244
/// you're looking for an example of a variable-length integer to use for your own project, move
226245
/// along, this is a rather poor design.
227246
pub(crate) struct BigSize(pub u64);
228-
impl Writeable for BigSize {
229-
#[inline]
230-
fn write(&self, writer: &mut Writer) -> Result<(), ::std::io::Error> {
247+
impl BigSize {
248+
pub fn write_write<W: Write>(&self, write: &mut W) -> Result<(), ::std::io::Error> {
231249
match self.0 {
232250
0...0xFC => {
233-
(self.0 as u8).write(writer)
251+
write.write_all(&[self.0 as u8])
234252
},
235253
0xFD...0xFFFF => {
236-
0xFDu8.write(writer)?;
237-
(self.0 as u16).write(writer)
254+
write.write_all(&[0xFDu8])?;
255+
write.write_all(&be16_to_array(self.0 as u16))
238256
},
239257
0x10000...0xFFFFFFFF => {
240-
0xFEu8.write(writer)?;
241-
(self.0 as u32).write(writer)
258+
write.write_all(&[0xFEu8])?;
259+
write.write_all(&be32_to_array(self.0 as u32))
242260
},
243261
_ => {
244-
0xFFu8.write(writer)?;
245-
(self.0 as u64).write(writer)
262+
write.write_all(&[0xFFu8])?;
263+
write.write_all(&be64_to_array(self.0 as u64))
246264
},
247265
}
248266
}
249267
}
268+
269+
impl Writeable for BigSize {
270+
#[inline]
271+
fn write(&self, writer: &mut Writer) -> Result<(), ::std::io::Error> {
272+
self.write_write(writer)
273+
}
274+
}
250275
impl Readable for BigSize {
251276
#[inline]
252277
fn read<R: Read>(reader: &mut R) -> Result<BigSize, DecodeError> {
@@ -609,10 +634,9 @@ impl<T: Writeable> Writeable for Option<T> {
609634
match *self {
610635
None => 0u8.write(w)?,
611636
Some(ref data) => {
612-
let mut len_calc = Writer::new();
613-
data.write(&mut len_calc).expect("No in-memory data may fail to serialize");
614-
BigSize(len_calc.len() as u64 + 1).write(w)?;
615-
data.write(w)?;
637+
let start = w.len();
638+
data.write(w).expect("No in-memory data may fail to serialize");
639+
w.insert_length(start, 1)?;
616640
}
617641
}
618642
Ok(())

lightning/src/util/ser_macros.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,12 @@
99

1010
macro_rules! encode_tlv {
1111
($stream: expr, {$(($type: expr, $field: expr)),*}) => { {
12-
use util::ser::{BigSize, Writer};
12+
use util::ser::BigSize;
1313
$(
1414
BigSize($type).write($stream)?;
15-
let mut len_calc = Writer::new();
16-
$field.write(&mut len_calc)?;
17-
BigSize(len_calc.len() as u64).write($stream)?;
15+
let start = $stream.len();
1816
$field.write($stream)?;
17+
$stream.insert_length(start, 0)?;
1918
)*
2019
} }
2120
}

0 commit comments

Comments
 (0)