http-parser 1.0.5 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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