Skip to content

Commit 6f63f5d

Browse files
Improvements to the str buffer copy.
1 parent 52d39b7 commit 6f63f5d

File tree

2 files changed

+17
-6
lines changed

2 files changed

+17
-6
lines changed

ext/hyper_ruby/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ publish = false
1010
crate-type = ["cdylib"]
1111

1212
[dependencies]
13-
magnus = { version = "0.6.2" }
13+
magnus = { version = "0.6.2", features = ["rb-sys"] }
1414
tokio = { version = "1", features = ["full"] }
1515
bytes = "1.5"
1616
tokio-stream = { version = "0.1", features = ["net"] }

ext/hyper_ruby/src/request.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use magnus::{value::{qnil, ReprValue}, RString, Value};
55
use bytes::Bytes;
66
use hyper::Request as HyperRequest;
77

8-
use rb_sys::{rb_str_cat, rb_str_resize, RSTRING_PTR, VALUE};
8+
use rb_sys::{rb_str_set_len, rb_str_modify, rb_str_modify_expand, rb_str_capacity, RSTRING_PTR, VALUE};
99

1010
// Type passed to ruby giving access to the request properties.
1111
#[magnus::wrap(class = "HyperRuby::Request")]
@@ -44,21 +44,32 @@ impl Request {
4444
buffer
4545
}
4646

47-
pub fn fill_body(&self, buffer: RString) -> usize {
47+
pub fn fill_body(&self, buffer: RString) -> i64 {
4848
let body = self.request.body();
49-
let body_len = body.len();
49+
let body_len: i64 = body.len().try_into().unwrap();
5050

5151
// Access the ruby string VALUE directly, and resize to 0 (keeping the capacity),
5252
// then copy our buffer into it.
5353
unsafe {
5454
let rb_value = buffer.as_value();
5555
let inner: VALUE = std::ptr::read(&rb_value as *const _ as *const VALUE);
56-
rb_str_resize(inner, body_len.try_into().unwrap());
56+
let existing_capacity = rb_str_capacity(inner) as i64;
57+
58+
// If the buffer is too small, expand it.
59+
if existing_capacity < body_len.try_into().unwrap() {
60+
rb_str_modify_expand(inner, body_len);
61+
}
62+
else {
63+
rb_str_modify(inner);
64+
}
65+
5766
if body_len > 0 {
5867
let body_ptr = body.as_ptr() as *const c_char;
5968
let rb_string_ptr = RSTRING_PTR(inner) as *mut c_char;
60-
std::ptr::copy(body_ptr, rb_string_ptr, body_len);
69+
std::ptr::copy(body_ptr, rb_string_ptr, body_len as usize);
6170
}
71+
72+
rb_str_set_len(inner, body_len);
6273
}
6374

6475
body_len

0 commit comments

Comments
 (0)