Class: Quicsilver::Protocol::ResponseParser

Inherits:
FrameParser
  • Object
show all
Defined in:
lib/quicsilver/protocol/response_parser.rb

Constant Summary collapse

PARSE_CACHE =

Class-level parse result cache: data → [status, headers, frames, body_str, trailers]

{}
PARSE_CACHE_MAX =
128
PARSE_OID_CACHE =
{}
PARSE_OID_CACHE_MAX =
128

Constants inherited from FrameParser

FrameParser::CONTROL_ONLY_SET, FrameParser::DEFAULT_DECODER, FrameParser::EMPTY_BODY

Instance Attribute Summary collapse

Attributes inherited from FrameParser

#bytes_consumed, #headers, #trailers

Instance Method Summary collapse

Methods inherited from FrameParser

#body, #frames

Constructor Details

#initialize(data, **opts) ⇒ ResponseParser

Returns a new instance of ResponseParser.



10
11
12
13
14
15
16
# File 'lib/quicsilver/protocol/response_parser.rb', line 10

def initialize(data, **opts)
  decoder = opts.delete(:decoder) || DEFAULT_DECODER
  super(decoder: decoder, max_body_size: opts[:max_body_size],
        max_header_size: opts[:max_header_size])
  @data = data
  @use_parse_cache = @decoder.equal?(DEFAULT_DECODER) && !@max_body_size && !@max_header_size
end

Instance Attribute Details

#statusObject (readonly)

Returns the value of attribute status.



8
9
10
# File 'lib/quicsilver/protocol/response_parser.rb', line 8

def status
  @status
end

Instance Method Details

#parseObject



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/quicsilver/protocol/response_parser.rb', line 68

def parse
  # Fast path: full parse result cache for default decoder with no limits
  if @use_parse_cache
    cached = PARSE_CACHE[@data]
    if cached
      @status = cached[0]
      @headers = cached[1]
      @frames = cached[2]
      @cached_body_str = cached[3]
      @trailers = cached[4] || {}
      return
    end
  end

  parse!
  cache_result if @use_parse_cache
end

#reparse(data) ⇒ Object

Combined reset + parse for maximum throughput (single method call)



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/quicsilver/protocol/response_parser.rb', line 30

def reparse(data)
  @data = data
  # Fastest path: same data object as last time — skip all cache lookups
  return if data.equal?(@last_data) && @headers

  if @use_parse_cache
    oid = data.object_id
    cached = PARSE_OID_CACHE[oid]
    unless cached
      cached = PARSE_CACHE[data]
      PARSE_OID_CACHE[oid] = cached if cached && PARSE_OID_CACHE.size < PARSE_OID_CACHE_MAX
    end
    if cached
      @status = cached[0]
      @headers = cached[1]
      @frames = cached[2]
      @cached_body_str = cached[3]
      @trailers = cached[4] || {}
      @last_data = data
      return
    end
  end
  @status = nil
  @headers = {}
  @trailers = {}
  @frames = nil
  @body = nil
  @cached_body_str = nil
  parse!
  cache_result if @use_parse_cache
end

#reset(data) ⇒ Object

Reset parser with new data for object reuse (avoids allocation overhead)



19
20
21
22
23
24
25
26
27
# File 'lib/quicsilver/protocol/response_parser.rb', line 19

def reset(data)
  @data = data
  @status = nil
  @headers = {}
  @trailers = {}
  @frames = nil
  @body = nil
  @cached_body_str = nil
end