@@ -32,31 +32,28 @@ struct GRPCMessageFramer {
3232 /// reserves capacity in powers of 2. This way, we can take advantage of the whole buffer.
3333 static let maximumWriteBufferLength = 65_536
3434
35- private var pendingMessages : OneOrManyQueue < PendingMessage >
36-
37- private struct PendingMessage {
38- let bytes : [ UInt8 ]
39- let compress : Bool
40- }
35+ private var pendingMessages : OneOrManyQueue < [ UInt8 ] >
4136
4237 private var writeBuffer : ByteBuffer
4338
39+ /// Create a new ``GRPCMessageFramer``.
4440 init ( ) {
4541 self . pendingMessages = OneOrManyQueue ( )
4642 self . writeBuffer = ByteBuffer ( )
4743 }
4844
4945 /// Queue the given bytes to be framed and potentially coalesced alongside other messages in a `ByteBuffer`.
5046 /// The resulting data will be returned when calling ``GRPCMessageFramer/next()``.
51- /// If `compress` is true, then the given bytes will be compressed using the configured compression algorithm.
52- mutating func append( _ bytes: [ UInt8 ] , compress: Bool ) {
53- self . pendingMessages. append ( PendingMessage ( bytes: bytes, compress: compress) )
47+ mutating func append( _ bytes: [ UInt8 ] ) {
48+ self . pendingMessages. append ( bytes)
5449 }
5550
5651 /// If there are pending messages to be framed, a `ByteBuffer` will be returned with the framed data.
5752 /// Data may also be compressed (if configured) and multiple frames may be coalesced into the same `ByteBuffer`.
53+ /// - Parameter compressor: An optional compressor: if present, payloads will be compressed; otherwise
54+ /// they'll be framed as-is.
5855 /// - Throws: If an error is encountered, such as a compression failure, an error will be thrown.
59- mutating func next( ) throws -> ByteBuffer ? {
56+ mutating func next( compressor : Zlib . Compressor ? = nil ) throws -> ByteBuffer ? {
6057 if self . pendingMessages. isEmpty {
6158 // Nothing pending: exit early.
6259 return nil
@@ -72,27 +69,34 @@ struct GRPCMessageFramer {
7269
7370 var requiredCapacity = 0
7471 for message in self . pendingMessages {
75- requiredCapacity += message. bytes . count + Self. metadataLength
72+ requiredCapacity += message. count + Self. metadataLength
7673 }
7774 self . writeBuffer. clear ( minimumCapacity: requiredCapacity)
7875
7976 while let message = self . pendingMessages. pop ( ) {
80- try self . encode ( message)
77+ try self . encode ( message, compressor : compressor )
8178 }
8279
8380 return self . writeBuffer
8481 }
8582
86- private mutating func encode( _ message: PendingMessage ) throws {
87- if message . compress {
83+ private mutating func encode( _ message: [ UInt8 ] , compressor : Zlib . Compressor ? ) throws {
84+ if let compressor {
8885 self . writeBuffer. writeInteger ( UInt8 ( 1 ) ) // Set compression flag
89- // TODO: compress message and write the compressed message length + bytes
86+
87+ // Write zeroes as length - we'll write the actual compressed size after compression.
88+ let lengthIndex = self . writeBuffer. writerIndex
89+ self . writeBuffer. writeInteger ( UInt32 ( 0 ) )
90+
91+ // Compress and overwrite the payload length field with the right length.
92+ let writtenBytes = try compressor. compress ( message, into: & self . writeBuffer)
93+ self . writeBuffer. setInteger ( UInt32 ( writtenBytes) , at: lengthIndex)
9094 } else {
9195 self . writeBuffer. writeMultipleIntegers (
9296 UInt8 ( 0 ) , // Clear compression flag
93- UInt32 ( message. bytes . count) // Set message length
97+ UInt32 ( message. count) // Set message length
9498 )
95- self . writeBuffer. writeBytes ( message. bytes )
99+ self . writeBuffer. writeBytes ( message)
96100 }
97101 }
98102}
0 commit comments