llhttp-ffi 0.0.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +7 -0
- data/LICENSE +353 -0
- data/README.md +37 -0
- data/ext/Rakefile +5 -0
- data/ext/llhttp/api.c +298 -0
- data/ext/llhttp/extconf.rb +6 -0
- data/ext/llhttp/http.c +172 -0
- data/ext/llhttp/llhttp.c +14894 -0
- data/ext/llhttp/llhttp.h +462 -0
- data/ext/llhttp/llhttp_ext.c +215 -0
- data/ext/x86_64-darwin/libllhttp-ext.bundle +0 -0
- data/ext/x86_64-darwin/llhttp/api.o +0 -0
- data/ext/x86_64-darwin/llhttp/http.o +0 -0
- data/ext/x86_64-darwin/llhttp/llhttp.o +0 -0
- data/ext/x86_64-darwin/llhttp/llhttp_ext.o +0 -0
- data/lib/llhttp.rb +48 -0
- data/lib/llhttp/delegate.rb +97 -0
- data/lib/llhttp/error.rb +8 -0
- data/lib/llhttp/parser.rb +158 -0
- data/lib/llhttp/version.rb +11 -0
- metadata +91 -0
@@ -0,0 +1,215 @@
|
|
1
|
+
/*
|
2
|
+
This software is licensed under the MPL-2.0 License.
|
3
|
+
|
4
|
+
Copyright Bryan Powell, 2020.
|
5
|
+
*/
|
6
|
+
|
7
|
+
#include <stdlib.h>
|
8
|
+
#include <string.h>
|
9
|
+
#include "llhttp.h"
|
10
|
+
|
11
|
+
typedef struct rb_llhttp_callbacks_s rb_llhttp_callbacks_t;
|
12
|
+
|
13
|
+
typedef int (*rb_llhttp_data_cb)(const char *data, size_t length);
|
14
|
+
typedef int (*rb_llhttp_cb)();
|
15
|
+
|
16
|
+
struct rb_llhttp_callbacks_s {
|
17
|
+
rb_llhttp_cb on_message_begin;
|
18
|
+
rb_llhttp_data_cb on_url;
|
19
|
+
rb_llhttp_data_cb on_status;
|
20
|
+
rb_llhttp_data_cb on_header_field;
|
21
|
+
rb_llhttp_data_cb on_header_value;
|
22
|
+
rb_llhttp_cb on_headers_complete;
|
23
|
+
rb_llhttp_data_cb on_body;
|
24
|
+
rb_llhttp_cb on_message_complete;
|
25
|
+
rb_llhttp_cb on_chunk_header;
|
26
|
+
rb_llhttp_cb on_chunk_complete;
|
27
|
+
rb_llhttp_cb on_url_complete;
|
28
|
+
rb_llhttp_cb on_status_complete;
|
29
|
+
rb_llhttp_cb on_header_field_complete;
|
30
|
+
rb_llhttp_cb on_header_value_complete;
|
31
|
+
};
|
32
|
+
|
33
|
+
int rb_llhttp_on_message_begin(llhttp_t *parser) {
|
34
|
+
rb_llhttp_callbacks_t* callbacks = parser->data;
|
35
|
+
return callbacks->on_message_begin();
|
36
|
+
}
|
37
|
+
|
38
|
+
int rb_llhttp_on_url(llhttp_t *parser, char *data, size_t length) {
|
39
|
+
rb_llhttp_callbacks_t* callbacks = parser->data;
|
40
|
+
callbacks->on_url(data, length);
|
41
|
+
return 0;
|
42
|
+
}
|
43
|
+
|
44
|
+
int rb_llhttp_on_status(llhttp_t *parser, char *data, size_t length) {
|
45
|
+
rb_llhttp_callbacks_t* callbacks = parser->data;
|
46
|
+
callbacks->on_status(data, length);
|
47
|
+
return 0;
|
48
|
+
}
|
49
|
+
|
50
|
+
int rb_llhttp_on_header_field(llhttp_t *parser, char *data, size_t length) {
|
51
|
+
rb_llhttp_callbacks_t* callbacks = parser->data;
|
52
|
+
callbacks->on_header_field(data, length);
|
53
|
+
return 0;
|
54
|
+
}
|
55
|
+
|
56
|
+
int rb_llhttp_on_header_value(llhttp_t *parser, char *data, size_t length) {
|
57
|
+
rb_llhttp_callbacks_t* callbacks = parser->data;
|
58
|
+
callbacks->on_header_value(data, length);
|
59
|
+
return 0;
|
60
|
+
}
|
61
|
+
|
62
|
+
int rb_llhttp_on_headers_complete(llhttp_t *parser) {
|
63
|
+
rb_llhttp_callbacks_t* callbacks = parser->data;
|
64
|
+
return callbacks->on_headers_complete();
|
65
|
+
}
|
66
|
+
|
67
|
+
int rb_llhttp_on_body(llhttp_t *parser, char *data, size_t length) {
|
68
|
+
rb_llhttp_callbacks_t* callbacks = parser->data;
|
69
|
+
callbacks->on_body(data, length);
|
70
|
+
return 0;
|
71
|
+
}
|
72
|
+
|
73
|
+
int rb_llhttp_on_message_complete(llhttp_t *parser) {
|
74
|
+
rb_llhttp_callbacks_t* callbacks = parser->data;
|
75
|
+
return callbacks->on_message_complete();
|
76
|
+
}
|
77
|
+
|
78
|
+
int rb_llhttp_on_chunk_header(llhttp_t *parser) {
|
79
|
+
rb_llhttp_callbacks_t* callbacks = parser->data;
|
80
|
+
return callbacks->on_chunk_header();
|
81
|
+
}
|
82
|
+
|
83
|
+
int rb_llhttp_on_chunk_complete(llhttp_t *parser) {
|
84
|
+
rb_llhttp_callbacks_t* callbacks = parser->data;
|
85
|
+
callbacks->on_chunk_complete();
|
86
|
+
return 0;
|
87
|
+
}
|
88
|
+
|
89
|
+
int rb_llhttp_on_url_complete(llhttp_t *parser) {
|
90
|
+
rb_llhttp_callbacks_t* callbacks = parser->data;
|
91
|
+
callbacks->on_url_complete();
|
92
|
+
return 0;
|
93
|
+
}
|
94
|
+
|
95
|
+
int rb_llhttp_on_status_complete(llhttp_t *parser) {
|
96
|
+
rb_llhttp_callbacks_t* callbacks = parser->data;
|
97
|
+
callbacks->on_status_complete();
|
98
|
+
return 0;
|
99
|
+
}
|
100
|
+
|
101
|
+
int rb_llhttp_on_header_field_complete(llhttp_t *parser) {
|
102
|
+
rb_llhttp_callbacks_t* callbacks = parser->data;
|
103
|
+
callbacks->on_header_field_complete();
|
104
|
+
return 0;
|
105
|
+
}
|
106
|
+
|
107
|
+
int rb_llhttp_on_header_value_complete(llhttp_t *parser) {
|
108
|
+
rb_llhttp_callbacks_t* callbacks = parser->data;
|
109
|
+
callbacks->on_header_value_complete();
|
110
|
+
return 0;
|
111
|
+
}
|
112
|
+
|
113
|
+
llhttp_t* rb_llhttp_init(int type, rb_llhttp_callbacks_t* callbacks) {
|
114
|
+
llhttp_t *parser = (llhttp_t *)malloc(sizeof(llhttp_t));
|
115
|
+
llhttp_settings_t *settings = (llhttp_settings_t *)malloc(sizeof(llhttp_settings_t));
|
116
|
+
|
117
|
+
llhttp_settings_init(settings);
|
118
|
+
|
119
|
+
if (callbacks->on_message_begin) {
|
120
|
+
settings->on_message_begin = (llhttp_cb)rb_llhttp_on_message_begin;
|
121
|
+
}
|
122
|
+
|
123
|
+
if (callbacks->on_url) {
|
124
|
+
settings->on_url = (llhttp_data_cb)rb_llhttp_on_url;
|
125
|
+
}
|
126
|
+
|
127
|
+
if (callbacks->on_status) {
|
128
|
+
settings->on_status = (llhttp_data_cb)rb_llhttp_on_status;
|
129
|
+
}
|
130
|
+
|
131
|
+
if (callbacks->on_header_field) {
|
132
|
+
settings->on_header_field = (llhttp_data_cb)rb_llhttp_on_header_field;
|
133
|
+
}
|
134
|
+
|
135
|
+
if (callbacks->on_header_value) {
|
136
|
+
settings->on_header_value = (llhttp_data_cb)rb_llhttp_on_header_value;
|
137
|
+
}
|
138
|
+
|
139
|
+
if (callbacks->on_headers_complete) {
|
140
|
+
settings->on_headers_complete = (llhttp_cb)rb_llhttp_on_headers_complete;
|
141
|
+
}
|
142
|
+
|
143
|
+
if (callbacks->on_body) {
|
144
|
+
settings->on_body = (llhttp_data_cb)rb_llhttp_on_body;
|
145
|
+
}
|
146
|
+
|
147
|
+
if (callbacks->on_message_complete) {
|
148
|
+
settings->on_message_complete = (llhttp_cb)rb_llhttp_on_message_complete;
|
149
|
+
}
|
150
|
+
|
151
|
+
if (callbacks->on_chunk_header) {
|
152
|
+
settings->on_chunk_header = (llhttp_cb)rb_llhttp_on_chunk_header;
|
153
|
+
}
|
154
|
+
|
155
|
+
if (callbacks->on_chunk_complete) {
|
156
|
+
settings->on_chunk_complete = (llhttp_cb)rb_llhttp_on_chunk_complete;
|
157
|
+
}
|
158
|
+
|
159
|
+
if (callbacks->on_url_complete) {
|
160
|
+
settings->on_url_complete = (llhttp_cb)rb_llhttp_on_url_complete;
|
161
|
+
}
|
162
|
+
|
163
|
+
if (callbacks->on_status_complete) {
|
164
|
+
settings->on_status_complete = (llhttp_cb)rb_llhttp_on_status_complete;
|
165
|
+
}
|
166
|
+
|
167
|
+
if (callbacks->on_header_field_complete) {
|
168
|
+
settings->on_header_field_complete = (llhttp_cb)rb_llhttp_on_header_field_complete;
|
169
|
+
}
|
170
|
+
|
171
|
+
if (callbacks->on_header_value_complete) {
|
172
|
+
settings->on_header_value_complete = (llhttp_cb)rb_llhttp_on_header_value_complete;
|
173
|
+
}
|
174
|
+
|
175
|
+
llhttp_init(parser, type, settings);
|
176
|
+
|
177
|
+
parser->data = callbacks;
|
178
|
+
|
179
|
+
return parser;
|
180
|
+
}
|
181
|
+
|
182
|
+
void rb_llhttp_free(llhttp_t* parser) {
|
183
|
+
if (parser) {
|
184
|
+
free(parser->settings);
|
185
|
+
free(parser);
|
186
|
+
}
|
187
|
+
}
|
188
|
+
|
189
|
+
uint64_t rb_llhttp_content_length(llhttp_t* parser) {
|
190
|
+
return parser->content_length;
|
191
|
+
}
|
192
|
+
|
193
|
+
const char* rb_llhttp_method_name(llhttp_t* parser) {
|
194
|
+
return llhttp_method_name(parser->method);
|
195
|
+
}
|
196
|
+
|
197
|
+
uint16_t rb_llhttp_status_code(llhttp_t* parser) {
|
198
|
+
return parser->status_code;
|
199
|
+
}
|
200
|
+
|
201
|
+
uint16_t rb_llhttp_http_major(llhttp_t* parser) {
|
202
|
+
return parser->http_major;
|
203
|
+
}
|
204
|
+
|
205
|
+
uint16_t rb_llhttp_http_minor(llhttp_t* parser) {
|
206
|
+
return parser->http_minor;
|
207
|
+
}
|
208
|
+
|
209
|
+
const char* rb_llhttp_errno_name(llhttp_errno_t errno) {
|
210
|
+
return llhttp_errno_name(errno);
|
211
|
+
}
|
212
|
+
|
213
|
+
const char* rb_llhttp_error_reason(llhttp_t* parser) {
|
214
|
+
return parser->reason;
|
215
|
+
}
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/lib/llhttp.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "ffi"
|
4
|
+
require "ffi-compiler/loader"
|
5
|
+
|
6
|
+
module LLHttp
|
7
|
+
require_relative "llhttp/delegate"
|
8
|
+
require_relative "llhttp/error"
|
9
|
+
require_relative "llhttp/parser"
|
10
|
+
require_relative "llhttp/version"
|
11
|
+
|
12
|
+
extend FFI::Library
|
13
|
+
ffi_lib(FFI::Compiler::Loader.find("llhttp-ext"))
|
14
|
+
|
15
|
+
callback :llhttp_data_cb, [:pointer, :size_t], :void
|
16
|
+
callback :llhttp_cb, [], :int
|
17
|
+
|
18
|
+
class Callbacks < FFI::Struct
|
19
|
+
layout :on_message_begin, :llhttp_cb,
|
20
|
+
:on_url, :llhttp_data_cb,
|
21
|
+
:on_status, :llhttp_data_cb,
|
22
|
+
:on_header_field, :llhttp_data_cb,
|
23
|
+
:on_header_value, :llhttp_data_cb,
|
24
|
+
:on_headers_complete, :llhttp_cb,
|
25
|
+
:on_body, :llhttp_data_cb,
|
26
|
+
:on_message_complete, :llhttp_cb,
|
27
|
+
:on_chunk_header, :llhttp_cb,
|
28
|
+
:on_chunk_complete, :llhttp_cb,
|
29
|
+
:on_url_complete, :llhttp_cb,
|
30
|
+
:on_status_complete, :llhttp_cb,
|
31
|
+
:on_header_field_complete, :llhttp_cb,
|
32
|
+
:on_header_value_complete, :llhttp_cb
|
33
|
+
end
|
34
|
+
|
35
|
+
attach_function :rb_llhttp_init, [:int, Callbacks.by_ref], :pointer
|
36
|
+
attach_function :rb_llhttp_content_length, [:pointer], :uint64
|
37
|
+
attach_function :rb_llhttp_method_name, [:pointer], :string
|
38
|
+
attach_function :rb_llhttp_status_code, [:pointer], :uint16
|
39
|
+
attach_function :rb_llhttp_http_major, [:pointer], :uint16
|
40
|
+
attach_function :rb_llhttp_http_minor, [:pointer], :uint16
|
41
|
+
attach_function :rb_llhttp_free, [:pointer], :void
|
42
|
+
|
43
|
+
attach_function :llhttp_execute, [:pointer, :pointer, :size_t], :int
|
44
|
+
attach_function :llhttp_errno_name, [:int], :string
|
45
|
+
attach_function :llhttp_get_error_reason, [:pointer], :string
|
46
|
+
attach_function :llhttp_should_keep_alive, [:pointer], :int
|
47
|
+
attach_function :llhttp_finish, [:pointer], :int
|
48
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LLHttp
|
4
|
+
# [public] Delegate for handling callbacks. Subclass this object and implement necessary methods.
|
5
|
+
#
|
6
|
+
# class Delegate < LLHttp::Delegate
|
7
|
+
# def on_message_begin
|
8
|
+
# ...
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# def on_url(url)
|
12
|
+
# ...
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# def on_status(status)
|
16
|
+
# ...
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# def on_header_field(field)
|
20
|
+
# ...
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# def on_header_value(value)
|
24
|
+
# ...
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# def on_headers_complete
|
28
|
+
# ...
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# def on_body(body)
|
32
|
+
# ...
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# def on_message_complete
|
36
|
+
# ...
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# def on_chunk_header
|
40
|
+
# ...
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# def on_chunk_complete
|
44
|
+
# ...
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# def on_url_complete
|
48
|
+
# ...
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# def on_status_complete
|
52
|
+
# ...
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# def on_header_field_complete
|
56
|
+
# ...
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
# def on_header_value_complete
|
60
|
+
# ...
|
61
|
+
# end
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
class Delegate
|
65
|
+
# private def internal_on_message_begin
|
66
|
+
# on_message_begin
|
67
|
+
|
68
|
+
# 0
|
69
|
+
# rescue
|
70
|
+
# -1
|
71
|
+
# end
|
72
|
+
|
73
|
+
# private def internal_on_headers_complete
|
74
|
+
# on_headers_complete
|
75
|
+
|
76
|
+
# 0
|
77
|
+
# rescue
|
78
|
+
# -1
|
79
|
+
# end
|
80
|
+
|
81
|
+
# private def internal_on_message_complete
|
82
|
+
# on_message_complete
|
83
|
+
|
84
|
+
# 0
|
85
|
+
# rescue
|
86
|
+
# -1
|
87
|
+
# end
|
88
|
+
|
89
|
+
# private def internal_on_chunk_header
|
90
|
+
# on_chunk_header
|
91
|
+
|
92
|
+
# 0
|
93
|
+
# rescue
|
94
|
+
# -1
|
95
|
+
# end
|
96
|
+
end
|
97
|
+
end
|
data/lib/llhttp/error.rb
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LLHttp
|
4
|
+
# [public] Wraps an llhttp context for parsing http requests and responses.
|
5
|
+
#
|
6
|
+
# class Delegate < LLHttp::Delegate
|
7
|
+
# def on_message_begin
|
8
|
+
# ...
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# ...
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# parser = LLHttp::Parser.new(Delegate.new, type: :request)
|
15
|
+
# parser << "GET / HTTP/1.1\r\n\r\n"
|
16
|
+
# parser.finish
|
17
|
+
#
|
18
|
+
# ...
|
19
|
+
#
|
20
|
+
# Introspection
|
21
|
+
#
|
22
|
+
# * `LLHttp::Parser#content_length` returns the content length of the current request.
|
23
|
+
# * `LLHttp::Parser#method_name` returns the method name of the current response.
|
24
|
+
# * `LLHttp::Parser#status_code` returns the status code of the current response.
|
25
|
+
# * `LLHttp::Parser#http_major` returns the major http version of the current request/response.
|
26
|
+
# * `LLHttp::Parser#http_minor` returns the minor http version of the current request/response.
|
27
|
+
# * `LLHttp::Parser#keep_alive?` returns `true` if there might be more messages.
|
28
|
+
#
|
29
|
+
# Finishing
|
30
|
+
#
|
31
|
+
# Call `LLHttp::Parser#finish` when processing is complete for the current request or response.
|
32
|
+
#
|
33
|
+
class Parser
|
34
|
+
LLHTTP_TYPES = {both: 0, request: 1, response: 2}.freeze
|
35
|
+
|
36
|
+
CALLBACKS = %i[
|
37
|
+
on_message_begin
|
38
|
+
on_headers_complete
|
39
|
+
on_message_complete
|
40
|
+
on_chunk_header
|
41
|
+
on_chunk_complete
|
42
|
+
on_url_complete
|
43
|
+
on_status_complete
|
44
|
+
on_header_field_complete
|
45
|
+
on_header_value_complete
|
46
|
+
].freeze
|
47
|
+
|
48
|
+
CALLBACKS_WITH_DATA = %i[
|
49
|
+
on_url
|
50
|
+
on_status
|
51
|
+
on_header_field
|
52
|
+
on_header_value
|
53
|
+
on_body
|
54
|
+
].freeze
|
55
|
+
|
56
|
+
# [public] The parser type; one of: `:both`, `:request`, or `:response`.
|
57
|
+
#
|
58
|
+
attr_reader :type
|
59
|
+
|
60
|
+
def initialize(delegate, type: :both)
|
61
|
+
@type, @delegate = type.to_sym, delegate
|
62
|
+
|
63
|
+
@callbacks = Callbacks.new
|
64
|
+
|
65
|
+
(CALLBACKS + CALLBACKS_WITH_DATA).each do |callback|
|
66
|
+
if delegate.respond_to?(callback)
|
67
|
+
@callbacks[callback] = method(callback).to_proc
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
@pointer = LLHttp.rb_llhttp_init(LLHTTP_TYPES.fetch(@type), @callbacks)
|
72
|
+
|
73
|
+
ObjectSpace.define_finalizer(self, self.class.free(@pointer))
|
74
|
+
end
|
75
|
+
|
76
|
+
# [public] Parse the given data.
|
77
|
+
#
|
78
|
+
def parse(data)
|
79
|
+
errno = LLHttp.llhttp_execute(@pointer, data, data.length)
|
80
|
+
raise build_error(errno) if errno > 0
|
81
|
+
end
|
82
|
+
alias_method :<<, :parse
|
83
|
+
|
84
|
+
# [public] Get the content length of the current request.
|
85
|
+
#
|
86
|
+
def content_length
|
87
|
+
LLHttp.rb_llhttp_content_length(@pointer)
|
88
|
+
end
|
89
|
+
|
90
|
+
# [public] Get the method of the current response.
|
91
|
+
#
|
92
|
+
def method_name
|
93
|
+
LLHttp.rb_llhttp_method_name(@pointer)
|
94
|
+
end
|
95
|
+
|
96
|
+
# [public] Get the status code of the current response.
|
97
|
+
#
|
98
|
+
def status_code
|
99
|
+
LLHttp.rb_llhttp_status_code(@pointer)
|
100
|
+
end
|
101
|
+
|
102
|
+
# [public] Get the major http version of the current request/response.
|
103
|
+
#
|
104
|
+
def http_major
|
105
|
+
LLHttp.rb_llhttp_http_major(@pointer)
|
106
|
+
end
|
107
|
+
|
108
|
+
# [public] Get the minor http version of the current request/response.
|
109
|
+
#
|
110
|
+
def http_minor
|
111
|
+
LLHttp.rb_llhttp_http_minor(@pointer)
|
112
|
+
end
|
113
|
+
|
114
|
+
# [public] Returns `true` if there might be more messages.
|
115
|
+
#
|
116
|
+
def keep_alive?
|
117
|
+
LLHttp.llhttp_should_keep_alive(@pointer) == 1
|
118
|
+
end
|
119
|
+
|
120
|
+
# [public] Get ready to parse the next request.
|
121
|
+
#
|
122
|
+
def finish
|
123
|
+
LLHttp.llhttp_finish(@pointer)
|
124
|
+
end
|
125
|
+
|
126
|
+
CALLBACKS.each do |callback|
|
127
|
+
class_eval(
|
128
|
+
<<~RB, __FILE__, __LINE__ + 1
|
129
|
+
private def #{callback}
|
130
|
+
@delegate.#{callback}
|
131
|
+
|
132
|
+
0
|
133
|
+
rescue
|
134
|
+
-1
|
135
|
+
end
|
136
|
+
RB
|
137
|
+
)
|
138
|
+
end
|
139
|
+
|
140
|
+
CALLBACKS_WITH_DATA.each do |callback|
|
141
|
+
class_eval(
|
142
|
+
<<~RB, __FILE__, __LINE__ + 1
|
143
|
+
private def #{callback}(buffer, length)
|
144
|
+
@delegate.#{callback}(buffer.get_bytes(0, length))
|
145
|
+
end
|
146
|
+
RB
|
147
|
+
)
|
148
|
+
end
|
149
|
+
|
150
|
+
private def build_error(errno)
|
151
|
+
Error.new("Error Parsing data: #{LLHttp.llhttp_errno_name(errno)} #{LLHttp.llhttp_get_error_reason(@pointer)}")
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.free(pointer)
|
155
|
+
proc { LLHttp.llhttp_free(@pointer) }
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|