1
1
// Copyright 2023-Present Datadog, Inc. https://www.datadoghq.com/
2
2
// SPDX-License-Identifier: Apache-2.0
3
3
4
+ use super :: UploadCompression ;
4
5
use bytes:: BufMut ;
5
6
use lz4_flex:: frame:: FrameEncoder ;
6
7
use prost:: encoding:: { encode_key, encode_varint, encoded_len_varint, key_len, WireType } ;
7
- use std:: io:: Write ;
8
+ use std:: io:: { self , Write } ;
9
+
10
+ enum Compressor {
11
+ None ,
12
+ Lz4 { zipper : FrameEncoder < Vec < u8 > > } ,
13
+ }
14
+
15
+ impl Compressor {
16
+ #[ inline]
17
+ fn compress ( & mut self , buffer : & mut Vec < u8 > ) -> io:: Result < ( ) > {
18
+ match self {
19
+ Compressor :: None => Ok ( ( ) ) ,
20
+ Compressor :: Lz4 { zipper } => {
21
+ zipper. write_all ( buffer) ?;
22
+ buffer. clear ( ) ;
23
+ Ok ( ( ) )
24
+ }
25
+ }
26
+ }
27
+ }
8
28
9
29
pub struct CompressedProtobufSerializer {
30
+ /// Buffer that protobuf is encoded into. Lz4 uses this as a temporary
31
+ /// buffer, while None uses this as the final output buffer.
10
32
buffer : Vec < u8 > ,
11
- zipper : FrameEncoder < Vec < u8 > > ,
33
+ compressor : Compressor ,
12
34
}
13
35
14
36
// I've opened a PR for a generic version of this upstream:
@@ -20,44 +42,54 @@ fn encode_str(tag: u32, value: &str, buf: &mut Vec<u8>) {
20
42
}
21
43
22
44
impl CompressedProtobufSerializer {
23
- pub fn encode ( & mut self , item : impl prost:: Message ) -> anyhow:: Result < ( ) > {
24
- item. encode ( & mut self . buffer ) ?;
25
- self . zipper . write_all ( & self . buffer ) ?;
26
- self . buffer . clear ( ) ;
27
- Ok ( ( ) )
45
+ pub fn encode ( & mut self , item : impl prost:: Message ) -> io:: Result < ( ) > {
46
+ let buffer = & mut self . buffer ;
47
+ item. encode ( buffer) ?;
48
+ self . compressor . compress ( buffer)
28
49
}
29
50
30
51
/// Only meant for string table strings. This is essentially an
31
52
/// implementation of [prost::Message::encode] but for any `AsRef<str>`,
32
53
/// and specialized for handling the unlikely OOM conditions of writing
33
54
/// into a `Vec<u8>`.
34
- pub ( crate ) fn encode_string_table_entry (
35
- & mut self ,
36
- item : impl AsRef < str > ,
37
- ) -> anyhow:: Result < ( ) > {
55
+ pub ( crate ) fn encode_string_table_entry ( & mut self , item : impl AsRef < str > ) -> io:: Result < ( ) > {
56
+ let buffer = & mut self . buffer ;
38
57
// In pprof, string tables are tag 6 on the Profile message.
39
58
let tag = 6u32 ;
40
59
let str = item. as_ref ( ) ;
41
60
let encoded_len = encoded_len_varint ( str. len ( ) as u64 ) ;
42
61
let required = key_len ( tag) + encoded_len + str. len ( ) ;
43
- if let Err ( err) = self . buffer . try_reserve ( required) {
44
- return Err ( anyhow:: Error :: from ( err)
45
- . context ( "failed to encode Protobuf str; insufficient buffer capacity" ) ) ;
46
- }
62
+ buffer. try_reserve ( required) ?;
47
63
48
- encode_str ( tag, str, & mut self . buffer ) ;
49
- self . zipper . write_all ( & self . buffer ) ?;
50
- self . buffer . clear ( ) ;
51
- Ok ( ( ) )
64
+ encode_str ( tag, str, buffer) ;
65
+ self . compressor . compress ( buffer)
52
66
}
53
67
54
- pub fn finish ( self ) -> anyhow:: Result < Vec < u8 > > {
55
- Ok ( self . zipper . finish ( ) ?)
68
+ pub fn finish ( self ) -> io:: Result < Vec < u8 > > {
69
+ match self . compressor {
70
+ Compressor :: None => Ok ( self . buffer ) ,
71
+ Compressor :: Lz4 { zipper } => {
72
+ debug_assert ! ( self . buffer. is_empty( ) ) ;
73
+ Ok ( zipper. finish ( ) ?)
74
+ }
75
+ }
56
76
}
57
77
58
- pub fn with_capacity ( capacity : usize ) -> Self {
78
+ pub fn with_config_and_capacity ( config : UploadCompression , capacity : usize ) -> Self {
79
+ // Final output buffer.
59
80
let buffer = Vec :: with_capacity ( capacity) ;
60
- let zipper = FrameEncoder :: new ( Vec :: with_capacity ( capacity) ) ;
61
- Self { buffer, zipper }
81
+ match config {
82
+ UploadCompression :: Off => Self {
83
+ buffer,
84
+ compressor : Compressor :: None ,
85
+ } ,
86
+ UploadCompression :: On | UploadCompression :: Lz4 => Self {
87
+ // Temporary input buffer.
88
+ buffer : Vec :: with_capacity ( 256 ) ,
89
+ compressor : Compressor :: Lz4 {
90
+ zipper : FrameEncoder :: new ( buffer) ,
91
+ } ,
92
+ } ,
93
+ }
62
94
}
63
95
}
0 commit comments