Class: Protocol::GRPC::Body::Readable

Inherits:
HTTP::Body::Wrapper
  • Object
show all
Defined in:
lib/protocol/grpc/body/readable.rb

Overview

Represents a readable body for gRPC messages with length-prefixed framing. This is the standard readable body for gRPC - all gRPC responses use message framing. Wraps the underlying HTTP body and transforms raw chunks into decoded gRPC messages.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(body, message_class: nil, encoding: nil) ⇒ Readable

Initialize a new readable body for gRPC messages.



39
40
41
42
43
44
# File 'lib/protocol/grpc/body/readable.rb', line 39

def initialize(body, message_class: nil, encoding: nil)
	super(body)
	@message_class = message_class
	@encoding = encoding
	@buffer = String.new.force_encoding(Encoding::BINARY)
end

Instance Attribute Details

#encodingObject (readonly)

Returns the value of attribute encoding.



47
48
49
# File 'lib/protocol/grpc/body/readable.rb', line 47

def encoding
  @encoding
end

#The compression encoding.(compressionencoding.) ⇒ Object (readonly)



47
# File 'lib/protocol/grpc/body/readable.rb', line 47

attr_reader :encoding

Class Method Details

.wrap(message, **options) ⇒ Object

Wrap the body of a message.



26
27
28
29
30
31
32
# File 'lib/protocol/grpc/body/readable.rb', line 26

def self.wrap(message, **options)
	if body = message.body
		message.body = self.new(body, **options)
	end
	
	return message.body
end

Instance Method Details

#readObject

Read the next gRPC message. Overrides Wrapper#read to transform raw HTTP body chunks into decoded gRPC messages.



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/protocol/grpc/body/readable.rb', line 52

def read
	# Read 5-byte prefix: 1 byte compression flag + 4 bytes length
	prefix = read_exactly(5)
	return nil unless prefix
	
	compressed = prefix[0].unpack1("C") == 1
	length = prefix[1..4].unpack1("N")
	
	# Read the message body:
	data = read_exactly(length)
	unless data
		raise Error.new(Status::INTERNAL, "Truncated gRPC frame: expected #{length} bytes, received 0")
	end
	
	# Decompress if needed:
	data = decompress(data) if compressed
	
	# Decode using message class if provided, otherwise return binary:
	# This allows binary mode for channel adapters
	if @message_class
		# Use protobuf gem's decode method:
		@message_class.decode(data)
	else
		data # Return raw binary
	end
end