http-parser 1.0.5 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,33 +1,35 @@
1
- # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
- require "http-parser/version"
4
-
5
- Gem::Specification.new do |s|
6
- s.name = "http-parser"
7
- s.version = HttpParser::VERSION
8
- s.authors = ["Stephen von Takach"]
9
- s.email = ["steve@cotag.me"]
10
- s.license = 'MIT'
11
- s.homepage = "https://github.com/cotag/http-parser"
12
- s.summary = "Ruby bindings to joyent/http-parser"
13
- s.description = <<-EOF
14
- A super fast http parser for ruby.
15
- Cross platform and multiple ruby implementation support thanks to ffi.
16
- EOF
17
-
18
-
19
- s.add_dependency 'ffi-compiler', '>= 0.0.2'
20
- s.add_dependency 'rake'
21
-
22
- s.add_development_dependency 'rspec'
23
- s.add_development_dependency 'yard'
24
-
25
-
26
- s.files = Dir["{lib}/**/*"] + %w(Rakefile http-parser.gemspec README.md LICENSE)
27
- s.files += ["ext/http-parser/http_parser.c", "ext/http-parser/http_parser.h"]
28
- s.test_files = Dir["spec/**/*"]
29
- s.extra_rdoc_files = ["README.md"]
30
-
31
- s.extensions << "ext/Rakefile"
32
- s.require_paths = ["lib"]
33
- end
1
+ # frozen_string_literal: true
2
+ # -*- encoding: utf-8 -*-
3
+
4
+ $:.push File.expand_path("../lib", __FILE__)
5
+ require "http-parser/version"
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "http-parser"
9
+ s.version = HttpParser::VERSION
10
+ s.authors = ["Stephen von Takach"]
11
+ s.email = ["steve@cotag.me"]
12
+ s.license = 'MIT'
13
+ s.homepage = "https://github.com/cotag/http-parser"
14
+ s.summary = "Ruby bindings to joyent/http-parser"
15
+ s.description = <<-EOF
16
+ A super fast http parser for ruby.
17
+ Cross platform and multiple ruby implementation support thanks to ffi.
18
+ EOF
19
+
20
+
21
+ s.add_dependency 'ffi-compiler', '>= 1.0', '< 2.0'
22
+
23
+ s.add_development_dependency 'rake', '~> 11.2'
24
+ s.add_development_dependency 'rspec', '~> 3.5'
25
+ s.add_development_dependency 'yard', '~> 0.9'
26
+
27
+
28
+ s.files = Dir["{lib}/**/*"] + %w(Rakefile http-parser.gemspec README.md LICENSE)
29
+ s.files += ["ext/http-parser/http_parser.c", "ext/http-parser/http_parser.h"]
30
+ s.test_files = Dir["spec/**/*"]
31
+ s.extra_rdoc_files = ["README.md"]
32
+
33
+ s.extensions << "ext/Rakefile"
34
+ s.require_paths = ["lib"]
35
+ end
@@ -1,9 +1,11 @@
1
- require "ffi" # Bindings to C libraries
2
-
3
- require "http-parser/ext" # Loads http-parser ext
4
- require "http-parser/errors" # http-parser error definitions
5
- require "http-parser/types" # http-parser data structures
6
- require "http-parser/parser" # the core http-parser abstraction
7
-
8
- module HttpParser
9
- end
1
+ # frozen_string_literal: true
2
+
3
+ require "ffi" # Bindings to C libraries
4
+
5
+ require "http-parser/ext" # Loads http-parser ext
6
+ require "http-parser/errors" # http-parser error definitions
7
+ require "http-parser/types" # http-parser data structures
8
+ require "http-parser/parser" # the core http-parser abstraction
9
+
10
+ module HttpParser
11
+ end
@@ -1,74 +1,77 @@
1
-
2
- module HttpParser
3
- class Error < StandardError
4
- class OK < Error; end
5
-
6
- # Any callback-related errors
7
- class CALLBACK < Error; end
8
-
9
- # Parsing-related errors
10
- class INVALID_EOF_STATE < Error; end
11
- class HEADER_OVERFLOW < Error; end
12
- class CLOSED_CONNECTION < Error; end
13
-
14
- class INVALID_VERSION < Error; end
15
- class INVALID_STATUS < Error; end
16
- class INVALID_METHOD < Error; end
17
- class INVALID_URL < Error; end
18
- class INVALID_HOST < Error; end
19
- class INVALID_PORT < Error; end
20
- class INVALID_PATH < Error; end
21
- class INVALID_QUERY_STRING < Error; end
22
- class INVALID_FRAGMENT < Error; end
23
- class LF_EXPECTED < Error; end
24
- class INVALID_HEADER_TOKEN < Error; end
25
- class INVALID_CONTENT_LENGTH < Error; end
26
- class INVALID_CHUNK_SIZE < Error; end
27
- class INVALID_CONSTANT < Error; end
28
- class INVALID_INTERNAL_STATE < Error; end
29
- class STRICT < Error; end
30
- class PAUSED < Error; end
31
-
32
- class UNKNOWN < Error; end
33
- end
34
-
35
- ERRORS = {
36
- :OK => Error::OK,
37
-
38
- :CB_message_begin => Error::CALLBACK,
39
- :CB_url => Error::CALLBACK,
40
- :CB_header_field => Error::CALLBACK,
41
- :CB_header_value => Error::CALLBACK,
42
- :CB_headers_complete => Error::CALLBACK,
43
- :CB_body => Error::CALLBACK,
44
- :CB_message_complete => Error::CALLBACK,
45
- :CB_status => Error::CALLBACK,
46
-
47
- :INVALID_EOF_STATE => Error::INVALID_EOF_STATE,
48
- :HEADER_OVERFLOW => Error::HEADER_OVERFLOW,
49
- :CLOSED_CONNECTION => Error::CLOSED_CONNECTION,
50
- :INVALID_VERSION => Error::INVALID_VERSION,
51
- :INVALID_STATUS => Error::INVALID_STATUS,
52
- :INVALID_METHOD => Error::INVALID_METHOD,
53
- :INVALID_URL => Error::INVALID_URL,
54
- :INVALID_HOST => Error::INVALID_HOST,
55
- :INVALID_PORT => Error::INVALID_PORT,
56
- :INVALID_PATH => Error::INVALID_PATH,
57
- :INVALID_QUERY_STRING => Error::INVALID_QUERY_STRING,
58
- :INVALID_FRAGMENT => Error::INVALID_FRAGMENT,
59
- :LF_EXPECTED => Error::LF_EXPECTED,
60
- :INVALID_HEADER_TOKEN => Error::INVALID_HEADER_TOKEN,
61
- :INVALID_CONTENT_LENGTH => Error::INVALID_CONTENT_LENGTH,
62
- :INVALID_CHUNK_SIZE => Error::INVALID_CHUNK_SIZE,
63
- :INVALID_CONSTANT => Error::INVALID_CONSTANT,
64
- :INVALID_INTERNAL_STATE => Error::INVALID_INTERNAL_STATE,
65
- :STRICT => Error::STRICT,
66
- :PAUSED => Error::PAUSED,
67
-
68
- :UNKNOWN => Error::UNKNOWN
69
- }
70
-
71
- attach_function :err_desc, :http_errno_description, [:int], :string, :blocking => true
72
- attach_function :err_name, :http_errno_name, [:int], :string, :blocking => true
73
- end
74
-
1
+ # frozen_string_literal: true
2
+
3
+ module HttpParser
4
+ class Error < StandardError
5
+ class OK < Error; end
6
+
7
+ # Any callback-related errors
8
+ class CALLBACK < Error; end
9
+
10
+ # Parsing-related errors
11
+ class INVALID_EOF_STATE < Error; end
12
+ class HEADER_OVERFLOW < Error; end
13
+ class CLOSED_CONNECTION < Error; end
14
+
15
+ class INVALID_VERSION < Error; end
16
+ class INVALID_STATUS < Error; end
17
+ class INVALID_METHOD < Error; end
18
+ class INVALID_URL < Error; end
19
+ class INVALID_HOST < Error; end
20
+ class INVALID_PORT < Error; end
21
+ class INVALID_PATH < Error; end
22
+ class INVALID_QUERY_STRING < Error; end
23
+ class INVALID_FRAGMENT < Error; end
24
+ class LF_EXPECTED < Error; end
25
+ class INVALID_HEADER_TOKEN < Error; end
26
+ class INVALID_CONTENT_LENGTH < Error; end
27
+ class INVALID_CHUNK_SIZE < Error; end
28
+ class INVALID_CONSTANT < Error; end
29
+ class INVALID_INTERNAL_STATE < Error; end
30
+ class STRICT < Error; end
31
+ class PAUSED < Error; end
32
+
33
+ class UNKNOWN < Error; end
34
+ end
35
+
36
+ ERRORS = {
37
+ :OK => Error::OK,
38
+
39
+ :CB_message_begin => Error::CALLBACK,
40
+ :CB_url => Error::CALLBACK,
41
+ :CB_header_field => Error::CALLBACK,
42
+ :CB_header_value => Error::CALLBACK,
43
+ :CB_headers_complete => Error::CALLBACK,
44
+ :CB_body => Error::CALLBACK,
45
+ :CB_message_complete => Error::CALLBACK,
46
+ :CB_status => Error::CALLBACK,
47
+ :CB_chunk_header => Error::CALLBACK,
48
+ :CB_chunk_complete => Error::CALLBACK,
49
+
50
+ :INVALID_EOF_STATE => Error::INVALID_EOF_STATE,
51
+ :HEADER_OVERFLOW => Error::HEADER_OVERFLOW,
52
+ :CLOSED_CONNECTION => Error::CLOSED_CONNECTION,
53
+ :INVALID_VERSION => Error::INVALID_VERSION,
54
+ :INVALID_STATUS => Error::INVALID_STATUS,
55
+ :INVALID_METHOD => Error::INVALID_METHOD,
56
+ :INVALID_URL => Error::INVALID_URL,
57
+ :INVALID_HOST => Error::INVALID_HOST,
58
+ :INVALID_PORT => Error::INVALID_PORT,
59
+ :INVALID_PATH => Error::INVALID_PATH,
60
+ :INVALID_QUERY_STRING => Error::INVALID_QUERY_STRING,
61
+ :INVALID_FRAGMENT => Error::INVALID_FRAGMENT,
62
+ :LF_EXPECTED => Error::LF_EXPECTED,
63
+ :INVALID_HEADER_TOKEN => Error::INVALID_HEADER_TOKEN,
64
+ :INVALID_CONTENT_LENGTH => Error::INVALID_CONTENT_LENGTH,
65
+ :INVALID_CHUNK_SIZE => Error::INVALID_CHUNK_SIZE,
66
+ :INVALID_CONSTANT => Error::INVALID_CONSTANT,
67
+ :INVALID_INTERNAL_STATE => Error::INVALID_INTERNAL_STATE,
68
+ :STRICT => Error::STRICT,
69
+ :PAUSED => Error::PAUSED,
70
+
71
+ :UNKNOWN => Error::UNKNOWN
72
+ }
73
+
74
+ attach_function :err_desc, :http_errno_description, [:int], :string
75
+ attach_function :err_name, :http_errno_name, [:int], :string
76
+ end
77
+
@@ -1,7 +1,9 @@
1
- require 'ffi'
2
- require 'ffi-compiler/loader'
3
-
4
- module HttpParser
5
- extend FFI::Library
6
- ffi_lib FFI::Compiler::Loader.find('http-parser-ext')
7
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'ffi'
4
+ require 'ffi-compiler/loader'
5
+
6
+ module HttpParser
7
+ extend FFI::Library
8
+ ffi_lib FFI::Compiler::Loader.find('http-parser-ext')
9
+ end
@@ -1,224 +1,258 @@
1
-
2
- module HttpParser
3
- class Parser
4
- CALLBACKS = [:on_message_begin, :on_url, :on_status, :on_header_field, :on_header_value, :on_headers_complete, :on_body, :on_message_complete]
5
-
6
- #
7
- # Returns a new request/response instance variable
8
- #
9
- def self.new_instance &block
10
- ::HttpParser::Instance.new &block
11
- end
12
-
13
-
14
- #
15
- # Initializes the Parser instance.
16
- #
17
- def initialize(callback_obj = nil)
18
- @settings = ::HttpParser::Settings.new
19
- @callbacks = {} # so GC doesn't clean them up on java
20
-
21
- if not callback_obj.nil?
22
- CALLBACKS.each do |callback|
23
- self.__send__(callback, &callback_obj.method(callback)) if callback_obj.respond_to? callback
24
- end
25
- end
26
-
27
- yield self if block_given?
28
- end
29
-
30
- #
31
- # Registers an `on_message_begin` callback.
32
- #
33
- # @yield [instance]
34
- # The given block will be called when the HTTP message begins.
35
- #
36
- # @yieldparam [HttpParser::Instance] instance
37
- # The state so far of the request / response being processed.
38
- #
39
- def on_message_begin(&block)
40
- cb = Callback.new(&block)
41
- @callbacks[:on_message_begin] = cb
42
- @settings[:on_message_begin] = cb
43
- end
44
-
45
- #
46
- # Registers an `on_url` callback.
47
- #
48
- # @yield [instance, url]
49
- # The given block will be called when the Request URI is recognized
50
- # within the Request-Line.
51
- #
52
- # @yieldparam [HttpParser::Instance] instance
53
- # The state so far of the request / response being processed.
54
- #
55
- # @yieldparam [String] url
56
- # The recognized Request URI.
57
- #
58
- # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2
59
- #
60
- def on_url(&block)
61
- cb = DataCallback.new(&block)
62
- @callbacks[:on_url] = cb
63
- @settings[:on_url] = cb
64
- end
65
-
66
- #
67
- # Registers an `on_status_complete` callback.
68
- #
69
- # @yield [instance]
70
- # The given block will be called when the status is recognized.
71
- #
72
- # @yieldparam [HttpParser::Instance] instance
73
- # The state so far of the request / response being processed.
74
- #
75
- def on_status(&block)
76
- cb = DataCallback.new(&block)
77
- @callbacks[:on_status] = cb
78
- @settings[:on_status] = cb
79
- end
80
-
81
- #
82
- # Registers an `on_header_field` callback.
83
- #
84
- # @yield [instance, field]
85
- # The given block will be called when a Header name is recognized
86
- # in the Headers.
87
- #
88
- # @yieldparam [HttpParser::Instance] instance
89
- # The state so far of the request / response being processed.
90
- #
91
- # @yieldparam [String] field
92
- # A recognized Header name.
93
- #
94
- # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.5
95
- #
96
- def on_header_field(&block)
97
- cb = DataCallback.new(&block)
98
- @callbacks[:on_header_field] = cb
99
- @settings[:on_header_field] = cb
100
- end
101
-
102
- #
103
- # Registers an `on_header_value` callback.
104
- #
105
- # @yield [instance, value]
106
- # The given block will be called when a Header value is recognized
107
- # in the Headers.
108
- #
109
- # @yieldparam [HttpParser::Instance] instance
110
- # The state so far of the request / response being processed.
111
- #
112
- # @yieldparam [String] value
113
- # A recognized Header value.
114
- #
115
- # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.5
116
- #
117
- def on_header_value(&block)
118
- cb = DataCallback.new(&block)
119
- @callbacks[:on_header_value] = cb
120
- @settings[:on_header_value] = cb
121
- end
122
-
123
- #
124
- # Registers an `on_headers_complete` callback.
125
- #
126
- # @yield [instance]
127
- # The given block will be called when the Headers stop.
128
- #
129
- # @yieldparam [HttpParser::Instance] instance
130
- # The state so far of the request / response being processed.
131
- #
132
- def on_headers_complete(&block)
133
- cb = Callback.new(&block)
134
- @callbacks[:on_headers_complete] = cb
135
- @settings[:on_headers_complete] = cb
136
- end
137
-
138
- #
139
- # Registers an `on_body` callback.
140
- #
141
- # @yield [instance, body]
142
- # The given block will be called when the body is recognized in the
143
- # message body.
144
- #
145
- # @yieldparam [HttpParser::Instance] instance
146
- # The state so far of the request / response being processed.
147
- #
148
- # @yieldparam [String] body
149
- # The full body or a chunk of the body from a chunked
150
- # Transfer-Encoded stream.
151
- #
152
- # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.5
153
- #
154
- def on_body(&block)
155
- cb = DataCallback.new(&block)
156
- @callbacks[:on_body] = cb
157
- @settings[:on_body] = cb
158
- end
159
-
160
- #
161
- # Registers an `on_message_begin` callback.
162
- #
163
- # @yield [instance]
164
- # The given block will be called when the message completes.
165
- #
166
- # @yieldparam [HttpParser::Instance] instance
167
- # The state so far of the request / response being processed.
168
- #
169
- def on_message_complete(&block)
170
- cb = Callback.new(&block)
171
- @callbacks[:on_message_complete] = cb
172
- @settings[:on_message_complete] = cb
173
- end
174
-
175
- #
176
- # Parses data.
177
- #
178
- # @param [HttpParser::Instance] inst
179
- # The state so far of the request / response being processed.
180
- #
181
- # @param [String] data
182
- # The data to parse against the instance specified.
183
- #
184
- # @return [Boolean]
185
- # Returns true if the data was parsed successfully.
186
- #
187
- def parse(inst, data)
188
- ::HttpParser.http_parser_execute(inst, @settings, data, data.length)
189
- return inst.error?
190
- end
191
-
192
-
193
- protected
194
-
195
-
196
- class Callback < ::FFI::Function
197
- #
198
- # Creates a new Parser callback.
199
- #
200
- def self.new(&block)
201
- super(:int, [::HttpParser::Instance.ptr]) do |parser|
202
- begin
203
- catch(:return) { yield(parser); 0 }
204
- rescue
205
- -1
206
- end
207
- end
208
- end
209
- end
210
-
211
- class DataCallback < ::FFI::Function
212
- def self.new(&block)
213
- super(:int, [::HttpParser::Instance.ptr, :pointer, :size_t]) do |parser, buffer, length|
214
- begin
215
- data = buffer.get_bytes(0, length)
216
- catch(:return) { yield(parser, data); 0 }
217
- rescue
218
- -1
219
- end
220
- end
221
- end
222
- end
223
- end
224
- end
1
+ # frozen_string_literal: true
2
+
3
+ module HttpParser
4
+ class Parser
5
+ CALLBACKS = [
6
+ :on_message_begin, :on_url, :on_status, :on_header_field, :on_header_value,
7
+ :on_headers_complete, :on_body, :on_message_complete, :on_chunk_header, :on_chunk_complete
8
+ ]
9
+
10
+ #
11
+ # Returns a new request/response instance variable
12
+ #
13
+ def self.new_instance &block
14
+ ::HttpParser::Instance.new &block
15
+ end
16
+
17
+
18
+ #
19
+ # Initializes the Parser instance.
20
+ #
21
+ def initialize(callback_obj = nil)
22
+ @settings = ::HttpParser::Settings.new
23
+ @callbacks = {} # so GC doesn't clean them up on java
24
+
25
+ if not callback_obj.nil?
26
+ CALLBACKS.each do |callback|
27
+ self.__send__(callback, &callback_obj.method(callback)) if callback_obj.respond_to? callback
28
+ end
29
+ end
30
+
31
+ yield self if block_given?
32
+ end
33
+
34
+ #
35
+ # Registers an `on_message_begin` callback.
36
+ #
37
+ # @yield [instance]
38
+ # The given block will be called when the HTTP message begins.
39
+ #
40
+ # @yieldparam [HttpParser::Instance] instance
41
+ # The state so far of the request / response being processed.
42
+ #
43
+ def on_message_begin(&block)
44
+ cb = Callback.new(&block)
45
+ @callbacks[:on_message_begin] = cb
46
+ @settings[:on_message_begin] = cb
47
+ end
48
+
49
+ #
50
+ # Registers an `on_url` callback.
51
+ #
52
+ # @yield [instance, url]
53
+ # The given block will be called when the Request URI is recognized
54
+ # within the Request-Line.
55
+ #
56
+ # @yieldparam [HttpParser::Instance] instance
57
+ # The state so far of the request / response being processed.
58
+ #
59
+ # @yieldparam [String] url
60
+ # The recognized Request URI.
61
+ #
62
+ # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2
63
+ #
64
+ def on_url(&block)
65
+ cb = DataCallback.new(&block)
66
+ @callbacks[:on_url] = cb
67
+ @settings[:on_url] = cb
68
+ end
69
+
70
+ #
71
+ # Registers an `on_status_complete` callback.
72
+ #
73
+ # @yield [instance]
74
+ # The given block will be called when the status is recognized.
75
+ #
76
+ # @yieldparam [HttpParser::Instance] instance
77
+ # The state so far of the request / response being processed.
78
+ #
79
+ def on_status(&block)
80
+ cb = DataCallback.new(&block)
81
+ @callbacks[:on_status] = cb
82
+ @settings[:on_status] = cb
83
+ end
84
+
85
+ #
86
+ # Registers an `on_header_field` callback.
87
+ #
88
+ # @yield [instance, field]
89
+ # The given block will be called when a Header name is recognized
90
+ # in the Headers.
91
+ #
92
+ # @yieldparam [HttpParser::Instance] instance
93
+ # The state so far of the request / response being processed.
94
+ #
95
+ # @yieldparam [String] field
96
+ # A recognized Header name.
97
+ #
98
+ # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.5
99
+ #
100
+ def on_header_field(&block)
101
+ cb = DataCallback.new(&block)
102
+ @callbacks[:on_header_field] = cb
103
+ @settings[:on_header_field] = cb
104
+ end
105
+
106
+ #
107
+ # Registers an `on_header_value` callback.
108
+ #
109
+ # @yield [instance, value]
110
+ # The given block will be called when a Header value is recognized
111
+ # in the Headers.
112
+ #
113
+ # @yieldparam [HttpParser::Instance] instance
114
+ # The state so far of the request / response being processed.
115
+ #
116
+ # @yieldparam [String] value
117
+ # A recognized Header value.
118
+ #
119
+ # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.5
120
+ #
121
+ def on_header_value(&block)
122
+ cb = DataCallback.new(&block)
123
+ @callbacks[:on_header_value] = cb
124
+ @settings[:on_header_value] = cb
125
+ end
126
+
127
+ #
128
+ # Registers an `on_headers_complete` callback.
129
+ #
130
+ # @yield [instance]
131
+ # The given block will be called when the Headers stop.
132
+ #
133
+ # @yieldparam [HttpParser::Instance] instance
134
+ # The state so far of the request / response being processed.
135
+ #
136
+ def on_headers_complete(&block)
137
+ cb = Callback.new(&block)
138
+ @callbacks[:on_headers_complete] = cb
139
+ @settings[:on_headers_complete] = cb
140
+ end
141
+
142
+ #
143
+ # Registers an `on_body` callback.
144
+ #
145
+ # @yield [instance, body]
146
+ # The given block will be called when the body is recognized in the
147
+ # message body.
148
+ #
149
+ # @yieldparam [HttpParser::Instance] instance
150
+ # The state so far of the request / response being processed.
151
+ #
152
+ # @yieldparam [String] body
153
+ # The full body or a chunk of the body from a chunked
154
+ # Transfer-Encoded stream.
155
+ #
156
+ # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.5
157
+ #
158
+ def on_body(&block)
159
+ cb = DataCallback.new(&block)
160
+ @callbacks[:on_body] = cb
161
+ @settings[:on_body] = cb
162
+ end
163
+
164
+ #
165
+ # Registers an `on_message_begin` callback.
166
+ #
167
+ # @yield [instance]
168
+ # The given block will be called when the message completes.
169
+ #
170
+ # @yieldparam [HttpParser::Instance] instance
171
+ # The state so far of the request / response being processed.
172
+ #
173
+ def on_message_complete(&block)
174
+ cb = Callback.new(&block)
175
+ @callbacks[:on_message_complete] = cb
176
+ @settings[:on_message_complete] = cb
177
+ end
178
+
179
+ #
180
+ # Registers an `on_chunk_header` callback.
181
+ #
182
+ # @yield [instance]
183
+ # The given block will be called when a new chunk header is received.
184
+ #
185
+ # @yieldparam [HttpParser::Instance] instance
186
+ # The state so far of the request / response being processed.
187
+ #
188
+ def on_chunk_header(&block)
189
+ cb = Callback.new(&block)
190
+ @callbacks[:on_message_complete] = cb
191
+ @settings[:on_message_complete] = cb
192
+ end
193
+
194
+ #
195
+ # Registers an `on_chunk_complete` callback.
196
+ #
197
+ # @yield [instance]
198
+ # The given block will be called when the current chunk completes.
199
+ #
200
+ # @yieldparam [HttpParser::Instance] instance
201
+ # The state so far of the request / response being processed.
202
+ #
203
+ def on_chunk_complete(&block)
204
+ cb = Callback.new(&block)
205
+ @callbacks[:on_message_complete] = cb
206
+ @settings[:on_message_complete] = cb
207
+ end
208
+
209
+ #
210
+ # Parses data.
211
+ #
212
+ # @param [HttpParser::Instance] inst
213
+ # The state so far of the request / response being processed.
214
+ #
215
+ # @param [String] data
216
+ # The data to parse against the instance specified.
217
+ #
218
+ # @return [Boolean]
219
+ # Returns true if the data was parsed successfully.
220
+ #
221
+ def parse(inst, data)
222
+ ::HttpParser.http_parser_execute(inst, @settings, data, data.length)
223
+ return inst.error?
224
+ end
225
+
226
+
227
+ protected
228
+
229
+
230
+ class Callback < ::FFI::Function
231
+ #
232
+ # Creates a new Parser callback.
233
+ #
234
+ def self.new(&block)
235
+ super(:int, [::HttpParser::Instance.ptr]) do |parser|
236
+ begin
237
+ catch(:return) { yield(parser); 0 }
238
+ rescue
239
+ -1
240
+ end
241
+ end
242
+ end
243
+ end
244
+
245
+ class DataCallback < ::FFI::Function
246
+ def self.new(&block)
247
+ super(:int, [::HttpParser::Instance.ptr, :pointer, :size_t]) do |parser, buffer, length|
248
+ begin
249
+ data = buffer.get_bytes(0, length)
250
+ catch(:return) { yield(parser, data); 0 }
251
+ rescue
252
+ -1
253
+ end
254
+ end
255
+ end
256
+ end
257
+ end
258
+ end