@@ -37,6 +37,7 @@ use crate::{
37
37
ApplicationId , BlobId , BlobType , BytecodeId , Destination , GenericApplicationId , MessageId ,
38
38
UserApplicationId ,
39
39
} ,
40
+ limited_writer:: { LimitedWriter , LimitedWriterError } ,
40
41
time:: { Duration , SystemTime } ,
41
42
} ;
42
43
@@ -861,14 +862,8 @@ impl fmt::Debug for Bytecode {
861
862
#[ derive( Error , Debug ) ]
862
863
pub enum DecompressionError {
863
864
/// Compressed bytecode is invalid, and could not be decompressed.
864
- #[ cfg( not( target_arch = "wasm32" ) ) ]
865
- #[ error( "Bytecode could not be decompressed" ) ]
866
- InvalidCompressedBytecode ( #[ source] io:: Error ) ,
867
-
868
- /// Compressed bytecode is invalid, and could not be decompressed.
869
- #[ cfg( target_arch = "wasm32" ) ]
870
- #[ error( "Bytecode could not be decompressed" ) ]
871
- InvalidCompressedBytecode ( #[ from] ruzstd:: frame_decoder:: FrameDecoderError ) ,
865
+ #[ error( "Bytecode could not be decompressed: {0}" ) ]
866
+ InvalidCompressedBytecode ( #[ from] io:: Error ) ,
872
867
}
873
868
874
869
/// A compressed WebAssembly module's bytecode.
@@ -880,20 +875,53 @@ pub struct CompressedBytecode {
880
875
pub compressed_bytes : Vec < u8 > ,
881
876
}
882
877
878
+ #[ cfg( not( target_arch = "wasm32" ) ) ]
883
879
impl CompressedBytecode {
880
+ /// Returns `true` if the decompressed size does not exceed the limit.
881
+ pub fn decompressed_size_at_most ( & self , limit : u64 ) -> Result < bool , DecompressionError > {
882
+ let mut decoder = zstd:: stream:: Decoder :: new ( & * self . compressed_bytes ) ?;
883
+ let limit = usize:: try_from ( limit) . unwrap_or ( usize:: MAX ) ;
884
+ let mut writer = LimitedWriter :: new ( io:: sink ( ) , limit) ;
885
+ match io:: copy ( & mut decoder, & mut writer) {
886
+ Ok ( _) => Ok ( true ) ,
887
+ Err ( error) => {
888
+ error. downcast :: < LimitedWriterError > ( ) ?;
889
+ Ok ( false )
890
+ }
891
+ }
892
+ }
893
+
884
894
/// Decompresses a [`CompressedBytecode`] into a [`Bytecode`].
885
- #[ cfg( not( target_arch = "wasm32" ) ) ]
886
895
pub fn decompress ( & self ) -> Result < Bytecode , DecompressionError > {
887
896
#[ cfg( with_metrics) ]
888
897
let _decompression_latency = BYTECODE_DECOMPRESSION_LATENCY . measure_latency ( ) ;
889
- let bytes = zstd:: stream:: decode_all ( & * self . compressed_bytes )
890
- . map_err ( DecompressionError :: InvalidCompressedBytecode ) ?;
898
+ let bytes = zstd:: stream:: decode_all ( & * self . compressed_bytes ) ?;
891
899
892
900
Ok ( Bytecode { bytes } )
893
901
}
902
+ }
903
+
904
+ #[ cfg( target_arch = "wasm32" ) ]
905
+ impl CompressedBytecode {
906
+ /// Returns `true` if the decompressed size does not exceed the limit.
907
+ pub fn decompressed_size_at_most ( & self , limit : u64 ) -> Result < bool , DecompressionError > {
908
+ let compressed_bytes = & * self . compressed_bytes ;
909
+ let limit = usize:: try_from ( limit) . unwrap_or ( usize:: MAX ) ;
910
+ let mut writer = LimitedWriter :: new ( io:: sink ( ) , limit) ;
911
+ let mut decoder = ruzstd:: streaming_decoder:: StreamingDecoder :: new ( compressed_bytes)
912
+ . map_err ( io:: Error :: other) ?;
913
+
914
+ // TODO(#2710): Decode multiple frames, if present
915
+ match io:: copy ( & mut decoder, & mut writer) {
916
+ Ok ( _) => Ok ( true ) ,
917
+ Err ( error) => {
918
+ error. downcast :: < LimitedWriterError > ( ) ?;
919
+ Ok ( false )
920
+ }
921
+ }
922
+ }
894
923
895
924
/// Decompresses a [`CompressedBytecode`] into a [`Bytecode`].
896
- #[ cfg( target_arch = "wasm32" ) ]
897
925
pub fn decompress ( & self ) -> Result < Bytecode , DecompressionError > {
898
926
use ruzstd:: { io:: Read , streaming_decoder:: StreamingDecoder } ;
899
927
@@ -902,10 +930,9 @@ impl CompressedBytecode {
902
930
903
931
let compressed_bytes = & * self . compressed_bytes ;
904
932
let mut bytes = Vec :: new ( ) ;
905
- let mut decoder = StreamingDecoder :: new ( compressed_bytes) ?;
933
+ let mut decoder = StreamingDecoder :: new ( compressed_bytes) . map_err ( io :: Error :: other ) ?;
906
934
907
- // Decode multiple frames, if present
908
- // (https://github.com/KillingSpark/zstd-rs/issues/57)
935
+ // TODO(#2710): Decode multiple frames, if present
909
936
while !decoder. get_ref ( ) . is_empty ( ) {
910
937
decoder
911
938
. read_to_end ( & mut bytes)
@@ -1035,6 +1062,17 @@ impl BlobContent {
1035
1062
pub fn blob_bytes ( & self ) -> BlobBytes {
1036
1063
BlobBytes ( self . inner_bytes ( ) )
1037
1064
}
1065
+
1066
+ /// Returns the size of the blob content in bytes.
1067
+ pub fn size ( & self ) -> usize {
1068
+ match self {
1069
+ BlobContent :: Data ( bytes) => bytes. len ( ) ,
1070
+ BlobContent :: ContractBytecode ( compressed_bytecode)
1071
+ | BlobContent :: ServiceBytecode ( compressed_bytecode) => {
1072
+ compressed_bytecode. compressed_bytes . len ( )
1073
+ }
1074
+ }
1075
+ }
1038
1076
}
1039
1077
1040
1078
impl From < Blob > for BlobContent {
0 commit comments