@@ -383,6 +383,40 @@ impl Readable for BigSize {
383383 }
384384}
385385
386+ /// The lightning protocol uses u16s for lengths in most cases. As our serialization framework
387+ /// primarily targets that, we must as well. However, because we may serialize objects that have
388+ /// more than 65K entries, we need to be able to store larger values. Thus, we define a variable
389+ /// length integer here that is backwards-compatible for values < 0xffff. We treat 0xffff as
390+ /// "read eight more bytes".
391+ ///
392+ /// To ensure we only have one valid encoding per value, we add 0xffff to values written as eight
393+ /// bytes. Thus, 0xfffe is serialized as 0xfffe, whereas 0xffff is serialized as
394+ /// 0xffff0000000000000000 (i.e. read-eight-bytes then zero).
395+ struct CollectionLength ( pub u64 ) ;
396+ impl Writeable for CollectionLength {
397+ #[ inline]
398+ fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , io:: Error > {
399+ if self . 0 < 0xffff {
400+ ( self . 0 as u16 ) . write ( writer)
401+ } else {
402+ 0xffffu16 . write ( writer) ?;
403+ ( self . 0 - 0xffff ) . write ( writer)
404+ }
405+ }
406+ }
407+
408+ impl Readable for CollectionLength {
409+ #[ inline]
410+ fn read < R : Read > ( r : & mut R ) -> Result < Self , DecodeError > {
411+ let mut val: u64 = <u16 as Readable >:: read ( r) ? as u64 ;
412+ if val == 0xffff {
413+ val = <u64 as Readable >:: read ( r) ?
414+ . checked_add ( 0xffff ) . ok_or ( DecodeError :: InvalidValue ) ?;
415+ }
416+ Ok ( CollectionLength ( val) )
417+ }
418+ }
419+
386420/// In TLV we occasionally send fields which only consist of, or potentially end with, a
387421/// variable-length integer which is simply truncated by skipping high zero bytes. This type
388422/// encapsulates such integers implementing [`Readable`]/[`Writeable`] for them.
@@ -597,7 +631,7 @@ macro_rules! impl_for_map {
597631 {
598632 #[ inline]
599633 fn write<W : Writer >( & self , w: & mut W ) -> Result <( ) , io:: Error > {
600- ( self . len( ) as u16 ) . write( w) ?;
634+ CollectionLength ( self . len( ) as u64 ) . write( w) ?;
601635 for ( key, value) in self . iter( ) {
602636 key. write( w) ?;
603637 value. write( w) ?;
@@ -611,9 +645,9 @@ macro_rules! impl_for_map {
611645 {
612646 #[ inline]
613647 fn read<R : Read >( r: & mut R ) -> Result <Self , DecodeError > {
614- let len: u16 = Readable :: read( r) ?;
615- let mut ret = $constr( len as usize ) ;
616- for _ in 0 ..len {
648+ let len: CollectionLength = Readable :: read( r) ?;
649+ let mut ret = $constr( len. 0 as usize ) ;
650+ for _ in 0 ..len. 0 {
617651 let k = K :: read( r) ?;
618652 let v_opt = V :: read( r) ?;
619653 if let Some ( v) = v_opt {
@@ -637,7 +671,7 @@ where T: Writeable + Eq + Hash
637671{
638672 #[ inline]
639673 fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
640- ( self . len ( ) as u16 ) . write ( w) ?;
674+ CollectionLength ( self . len ( ) as u64 ) . write ( w) ?;
641675 for item in self . iter ( ) {
642676 item. write ( w) ?;
643677 }
@@ -650,9 +684,9 @@ where T: Readable + Eq + Hash
650684{
651685 #[ inline]
652686 fn read < R : Read > ( r : & mut R ) -> Result < Self , DecodeError > {
653- let len: u16 = Readable :: read ( r) ?;
654- let mut ret = HashSet :: with_capacity ( len as usize ) ;
655- for _ in 0 ..len {
687+ let len: CollectionLength = Readable :: read ( r) ?;
688+ let mut ret = HashSet :: with_capacity ( cmp :: min ( len. 0 as usize , MAX_BUF_SIZE / core :: mem :: size_of :: < T > ( ) ) ) ;
689+ for _ in 0 ..len. 0 {
656690 if !ret. insert ( T :: read ( r) ?) {
657691 return Err ( DecodeError :: InvalidValue )
658692 }
@@ -667,7 +701,7 @@ macro_rules! impl_for_vec {
667701 impl <$( $name : Writeable ) ,* > Writeable for Vec <$ty> {
668702 #[ inline]
669703 fn write<W : Writer >( & self , w: & mut W ) -> Result <( ) , io:: Error > {
670- ( self . len( ) as u16 ) . write( w) ?;
704+ CollectionLength ( self . len( ) as u64 ) . write( w) ?;
671705 for elem in self . iter( ) {
672706 elem. write( w) ?;
673707 }
@@ -678,9 +712,9 @@ macro_rules! impl_for_vec {
678712 impl <$( $name : Readable ) ,* > Readable for Vec <$ty> {
679713 #[ inline]
680714 fn read<R : Read >( r: & mut R ) -> Result <Self , DecodeError > {
681- let len: u16 = Readable :: read( r) ?;
682- let mut ret = Vec :: with_capacity( cmp:: min( len as usize , MAX_BUF_SIZE / core:: mem:: size_of:: <$ty>( ) ) ) ;
683- for _ in 0 ..len {
715+ let len: CollectionLength = Readable :: read( r) ?;
716+ let mut ret = Vec :: with_capacity( cmp:: min( len. 0 as usize , MAX_BUF_SIZE / core:: mem:: size_of:: <$ty>( ) ) ) ;
717+ for _ in 0 ..len. 0 {
684718 if let Some ( val) = MaybeReadable :: read( r) ? {
685719 ret. push( val) ;
686720 }
@@ -694,18 +728,23 @@ macro_rules! impl_for_vec {
694728impl Writeable for Vec < u8 > {
695729 #[ inline]
696730 fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
697- ( self . len ( ) as u16 ) . write ( w) ?;
731+ CollectionLength ( self . len ( ) as u64 ) . write ( w) ?;
698732 w. write_all ( & self )
699733 }
700734}
701735
702736impl Readable for Vec < u8 > {
703737 #[ inline]
704738 fn read < R : Read > ( r : & mut R ) -> Result < Self , DecodeError > {
705- let len: u16 = Readable :: read ( r) ?;
706- let mut ret = Vec :: with_capacity ( len as usize ) ;
707- ret. resize ( len as usize , 0 ) ;
708- r. read_exact ( & mut ret) ?;
739+ let mut len: CollectionLength = Readable :: read ( r) ?;
740+ let mut ret = Vec :: new ( ) ;
741+ while len. 0 > 0 {
742+ let readamt = cmp:: min ( len. 0 as usize , MAX_BUF_SIZE ) ;
743+ let readstart = ret. len ( ) ;
744+ ret. resize ( readstart + readamt, 0 ) ;
745+ r. read_exact ( & mut ret[ readstart..] ) ?;
746+ len. 0 -= readamt as u64 ;
747+ }
709748 Ok ( ret)
710749 }
711750}
@@ -1040,7 +1079,7 @@ impl Readable for () {
10401079impl Writeable for String {
10411080 #[ inline]
10421081 fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
1043- ( self . len ( ) as u16 ) . write ( w) ?;
1082+ CollectionLength ( self . len ( ) as u64 ) . write ( w) ?;
10441083 w. write_all ( self . as_bytes ( ) )
10451084 }
10461085}
0 commit comments