diff --git a/.vscode/launch.json b/.vscode/launch.json
index f42a57f..a28e4ef 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -29,15 +29,15 @@
{
"type": "lldb",
"request": "launch",
- "name": "Debug example 'buffer'",
+ "name": "Debug example 'blocking'",
"cargo": {
"args": [
"build",
- "--example=buffer",
+ "--example=blocking",
"--package=cronet-rs"
],
"filter": {
- "name": "buffer",
+ "name": "blocking",
"kind": "example"
}
},
diff --git a/README.md b/README.md
index fb96c9f..e19f4a6 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@ $ cd cronet-rs
Then, follow the steps to build the project:
-1. Get the latest cronet binaries: [build from source](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/components/cronet/build_instructions.md) or get prebuilt binaries from somewhere (if you know a reputable source, [let me know](https://github.com/sleeyax/cronet-rs/issues/new)!).
+1. Get the latest cronet binaries: [build from source](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/components/cronet/build_instructions.md) or download prebuilt binaries from [here](https://github.com/sleeyax/cronet-binaries/releases).
2. Place all `.h` header files in `src` and all binaries (`.so`, `.dll`, `.dylib`) in `bin`.
3. Run `cargo build`. This should trigger `bindgen` to (re)generate the bindings.
@@ -24,12 +24,12 @@ Then, follow the steps to build the project:
Maintenance of this project is made possible by all the contributors and sponsors.
If you'd like to sponsor this project and have your avatar or company logo appear below click [here](https://github.com/sponsors/sleeyax). 💖
-
+
## Related projects
Other projects that are related to this project and might interest you:
-- [Cronet in C#](https://github.com/sleeyax/CronetSharp)
-- [Cronet in go](https://github.com/SagerNet/cronet-go)
+- [Cronet bindings for C#](https://github.com/sleeyax/CronetSharp)
+- [Cronet bindings for go](https://github.com/sleeyax/cronet-go)
- [NaïveProxy](https://github.com/klzgrad/naiveproxy)
diff --git a/examples/blocking.rs b/examples/blocking.rs
new file mode 100644
index 0000000..7df6a02
--- /dev/null
+++ b/examples/blocking.rs
@@ -0,0 +1,36 @@
+use cronet_rs::client::{Body, Client};
+
+fn main() {
+ let client = Client::new();
+
+ println!("sending GET request...");
+ let request = http::Request::builder()
+ .method("GET")
+ .uri("https://httpbin.org/anything")
+ .body(Body::default())
+ .unwrap();
+ let result = client.send(request);
+ print_result(result);
+
+ println!("sending POST request...");
+ let request = http::Request::builder()
+ .method("POST")
+ .uri("https://httpbin.org/anything")
+ .header("content-type", "application/x-www-form-urlencoded")
+ .body(Body::from("Hello, world"))
+ .unwrap();
+ let result = client.send(request);
+ print_result(result);
+}
+
+fn print_result(result: Result, cronet_rs::client::ClientError>) {
+ match result {
+ Ok(response) => {
+ println!("Status: {}", response.status());
+ println!("Headers: {:#?}", response.headers());
+ let body = response.body().as_bytes().unwrap();
+ println!("Body: {}", String::from_utf8_lossy(body));
+ }
+ Err(error) => println!("Error: {}", error),
+ }
+}
diff --git a/src/buffer.rs b/src/buffer.rs
index 24373ef..b37c3a5 100644
--- a/src/buffer.rs
+++ b/src/buffer.rs
@@ -1,3 +1,5 @@
+use std::slice;
+
use crate::{
BufferCallback, Cronet_BufferPtr, Cronet_Buffer_Create, Cronet_Buffer_Destroy,
Cronet_Buffer_GetData, Cronet_Buffer_GetSize, Cronet_Buffer_InitWithAlloc,
@@ -55,6 +57,10 @@ impl Buffer {
unsafe { Cronet_Buffer_GetSize(self.ptr) }
}
+ pub(crate) fn data_ptr(&self) -> Cronet_RawDataPtr {
+ unsafe { Cronet_Buffer_GetData(self.ptr) }
+ }
+
pub fn data(&self) -> Box {
unsafe {
let dataPtr: Cronet_RawDataPtr = self.data_ptr();
@@ -62,8 +68,11 @@ impl Buffer {
}
}
- pub(crate) fn data_ptr(&self) -> Cronet_RawDataPtr {
- unsafe { Cronet_Buffer_GetData(self.ptr) }
+ pub fn data_slice(&self, size: usize) -> &[T] {
+ unsafe {
+ let slice = slice::from_raw_parts(self.data_ptr() as *mut T, size);
+ slice
+ }
}
/// Write arbitrary data to the buffer.
@@ -74,7 +83,8 @@ impl Buffer {
///
/// * `data` - The data to write to the buffer.
/// * `data_size` - The size of the data to write to the buffer. Must be less than or equal to the buffer's size.
- pub fn write(&self, data: Box, data_size: u64) -> Result<(), &'static str> {
+ #[allow(dead_code)]
+ pub(crate) fn write(&self, data: Box, data_size: u64) -> Result<(), &'static str> {
let src = Box::into_raw(data);
let src_size = data_size;
let dst = self.data_ptr() as *mut T;
@@ -90,6 +100,23 @@ impl Buffer {
Ok(())
}
+
+ pub(crate) fn write_slice(&self, data: &[T], data_size: u64) -> Result<(), &'static str> {
+ let src = data.as_ptr();
+ let src_size = data_size;
+ let dst = self.data_ptr() as *mut T;
+ let dst_size = self.size();
+
+ if dst_size < src_size {
+ return Err("Buffer is too small to hold the specified data");
+ }
+
+ unsafe {
+ std::ptr::copy_nonoverlapping(src, dst, src_size as usize);
+ }
+
+ Ok(())
+ }
}
impl Destroy for Buffer {
diff --git a/src/buffer_callback.rs b/src/buffer_callback.rs
index 13cc888..78c00ca 100644
--- a/src/buffer_callback.rs
+++ b/src/buffer_callback.rs
@@ -6,7 +6,7 @@ use crate::{
};
static mut BUFFER_CALLBACKS: Lazy> =
- Lazy::new(|| CronetCallbacks::new());
+ Lazy::new(CronetCallbacks::new);
#[no_mangle]
unsafe extern "C" fn cronetBufferCallbackOnDestroy(
diff --git a/src/client/body.rs b/src/client/body.rs
index 31f0121..0c3de43 100644
--- a/src/client/body.rs
+++ b/src/client/body.rs
@@ -1,7 +1,7 @@
// This implementation is inspired by: https://github.com/seanmonstar/reqwest/blob/6792f697fcdb27c47dcbf7bd05f23368d1d4ac80/src/blocking/body.rs
// License: https://github.com/seanmonstar/reqwest/blob/master/LICENSE-MIT
-use bytes::Bytes;
+use bytes::{Bytes, BytesMut};
use std::fmt;
use std::fs::File;
use std::io::Read;
@@ -30,6 +30,18 @@ impl Body {
match self.kind {
Kind::Reader(_, _) => None,
Kind::Bytes(ref bytes) => Some(bytes.as_ref()),
+ Kind::BytesMut(ref bytes) => Some(bytes.as_ref()),
+ }
+ }
+
+ /// Returns the body as a mutable byte slice.
+ /// Useful to build the body of a HTTP response.
+ /// For HTTP requests this method returns `None`.
+ pub fn as_bytes_mut(&mut self) -> Option<&mut BytesMut> {
+ match self.kind {
+ Kind::Reader(_, _) => None,
+ Kind::Bytes(_) => None,
+ Kind::BytesMut(ref mut bytes) => Some(bytes),
}
}
@@ -37,6 +49,7 @@ impl Body {
match self.kind {
Kind::Reader(_, len) => len,
Kind::Bytes(ref bytes) => Some(bytes.len() as u64),
+ Kind::BytesMut(ref bytes) => Some(bytes.len() as u64),
}
}
@@ -49,6 +62,7 @@ impl Body {
enum Kind {
Reader(Box, Option),
Bytes(Bytes),
+ BytesMut(BytesMut),
}
impl Kind {
@@ -56,6 +70,15 @@ impl Kind {
match self {
Kind::Reader(..) => None,
Kind::Bytes(v) => Some(Kind::Bytes(v.clone())),
+ Kind::BytesMut(v) => Some(Kind::BytesMut(v.clone())),
+ }
+ }
+}
+
+impl Default for Body {
+ fn default() -> Body {
+ Body {
+ kind: Kind::BytesMut(BytesMut::new()),
}
}
}
@@ -118,6 +141,7 @@ impl fmt::Debug for Kind {
.field("length", &DebugLength(v))
.finish(),
Kind::Bytes(ref v) => fmt::Debug::fmt(v, f),
+ Kind::BytesMut(ref v) => fmt::Debug::fmt(v, f),
}
}
}
diff --git a/src/client/body_upload_provider.rs b/src/client/body_upload_provider.rs
index c7de2de..b448f92 100644
--- a/src/client/body_upload_provider.rs
+++ b/src/client/body_upload_provider.rs
@@ -29,9 +29,9 @@ impl<'a> UploadDataProviderHandler for BodyUploadDataProvider<'a> {
return;
}
- match buffer.write(Box::new(bytes), len) {
+ match buffer.write_slice(bytes, len) {
Ok(_) => {
- sink.on_read_succeeded(len, true); // TODO: implement chunked reads
+ sink.on_read_succeeded(len, false); // TODO: implement chunked reads
}
Err(err) => {
sink.on_read_error(err);
@@ -100,9 +100,9 @@ mod tests {
// Read the modified buffer again by its pointer.
let buffer = Buffer { ptr };
- let actual = buffer.data::<&[u8]>();
+ let actual = buffer.data_slice::(4);
assert_eq!(actual.len(), expected.len());
- assert_eq!(*actual, expected.as_bytes());
+ assert_eq!(actual, expected.as_bytes());
buffer.destroy();
}
diff --git a/src/client/client.rs b/src/client/client.rs
index fa0c22d..5e942cb 100644
--- a/src/client/client.rs
+++ b/src/client/client.rs
@@ -1,10 +1,11 @@
-use std::thread;
+use std::{sync::mpsc, thread};
-use crate::{Destroy, Engine, EngineParams, Executor, UrlRequestParams};
+use crate::{
+ client::ClientError, Destroy, Engine, EngineParams, EngineResult, Executor, UrlRequest,
+ UrlRequestCallback, UrlRequestParams,
+};
-use super::Body;
-
-type ShouldRedirectFn = fn(new_location_url: &str) -> bool;
+use super::{Body, ResponseHandler, ShouldRedirectFn, Status};
pub struct Client {
pub should_redirect: ShouldRedirectFn,
@@ -51,12 +52,41 @@ impl Client {
self.should_redirect = should_redirect;
}
- pub fn send(&self, request: http::Request) -> http::Result> {
+ pub fn send(&self, request: http::Request) -> Result, ClientError> {
+ let uri = request.uri().to_string();
+
let request_parameters = UrlRequestParams::from(request);
request_parameters.set_upload_data_executor(&self.executor);
- // TODO: implement response handler
+ let (tx, rx) = mpsc::channel::();
+ let response_handler = ResponseHandler::new(self.should_redirect, tx);
+ let callback = UrlRequestCallback::new(response_handler);
+ let url_request = UrlRequest::new();
+ url_request.init_with_params(
+ &self.engine,
+ uri.as_str(),
+ &request_parameters,
+ &callback,
+ &self.executor,
+ );
+ // request_parameters.destroy();
+ let result = url_request.start();
+ if result != EngineResult::Success {
+ return Result::Err(ClientError::EngineError(result));
+ }
+
+ let status = rx.recv().unwrap();
+
+ match status {
+ Status::Success(res) => Result::Ok(res),
+ Status::Canceled => Result::Err(ClientError::CancellationError),
+ Status::Error(e) => Result::Err(ClientError::CronetError(e)),
+ }
+ }
+}
- http::Result::Ok(http::Response::new(Body::from("")))
+impl Default for Client {
+ fn default() -> Self {
+ Self::new()
}
}
diff --git a/src/client/error.rs b/src/client/error.rs
new file mode 100644
index 0000000..cdbf132
--- /dev/null
+++ b/src/client/error.rs
@@ -0,0 +1,38 @@
+use core::fmt;
+
+use crate::{CronetError, EngineResult};
+
+pub enum ClientError {
+ /// Internal cronet error.
+ CronetError(CronetError),
+ /// The request was cancelled.
+ CancellationError,
+ /// Unexpected cronet engine result.
+ EngineError(EngineResult),
+}
+
+impl From for ClientError {
+ fn from(error: CronetError) -> Self {
+ Self::CronetError(error)
+ }
+}
+
+impl fmt::Display for ClientError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Self::CronetError(error) => write!(f, "{}", error),
+ Self::CancellationError => write!(f, "Request was cancelled"),
+ Self::EngineError(error) => write!(f, "Unexpected engine result: {:?}", error),
+ }
+ }
+}
+
+impl fmt::Debug for ClientError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Self::CronetError(error) => write!(f, "{}", error),
+ Self::CancellationError => write!(f, "Request was cancelled"),
+ Self::EngineError(error) => write!(f, "Unexpected engine result: {:?}", error),
+ }
+ }
+}
diff --git a/src/client/mod.rs b/src/client/mod.rs
index f7a4312..c0d9d4a 100644
--- a/src/client/mod.rs
+++ b/src/client/mod.rs
@@ -1,7 +1,12 @@
mod body;
mod body_upload_provider;
+#[allow(clippy::module_inception)]
mod client;
+mod error;
+mod response_handler;
pub use body::*;
pub use body_upload_provider::*;
pub use client::*;
+pub use error::*;
+pub use response_handler::*;
diff --git a/src/client/response_handler.rs b/src/client/response_handler.rs
new file mode 100644
index 0000000..f4aa55e
--- /dev/null
+++ b/src/client/response_handler.rs
@@ -0,0 +1,124 @@
+use std::{mem, sync::mpsc::Sender};
+
+use bytes::BufMut;
+use http::Response;
+
+use crate::{
+ Buffer, CronetError, Destroy, UrlRequest, UrlRequestCallback, UrlRequestCallbackHandler,
+ UrlResponseInfo,
+};
+
+use super::Body;
+
+pub type ShouldRedirectFn = fn(new_location_url: &str) -> bool;
+
+#[derive(Debug)]
+pub enum Status {
+ Success(Response),
+ Canceled,
+ Error(CronetError),
+}
+
+pub struct ResponseHandler {
+ should_redirect: ShouldRedirectFn,
+ response: Response,
+ tx: Sender,
+ buffer: Option,
+ buffer_size: u64,
+}
+
+impl ResponseHandler {
+ pub fn new(should_redirect: ShouldRedirectFn, tx: Sender) -> Self {
+ Self {
+ should_redirect,
+ response: Response::default(),
+ tx,
+ buffer: None,
+ buffer_size: 512,
+ }
+ }
+
+ /// Sets the buffer size for reading the response body.
+ /// The default is `512` bytes.
+ pub fn set_buffer_size(&mut self, buffer_size: u64) {
+ self.buffer_size = buffer_size;
+ }
+
+ /// Continues reading the response body.
+ fn read(&mut self, req: UrlRequest) {
+ if let Some(old_buffer) = &self.buffer {
+ old_buffer.destroy();
+ }
+
+ let buffer = Buffer::new_with_size(self.buffer_size);
+ self.buffer = Some(Buffer { ptr: buffer.ptr });
+
+ req.read(buffer);
+ }
+}
+
+impl UrlRequestCallbackHandler for ResponseHandler {
+ fn on_redirect_received(
+ &mut self,
+ _: UrlRequestCallback,
+ request: UrlRequest,
+ info: UrlResponseInfo,
+ new_location_url: &str,
+ ) {
+ if (self.should_redirect)(new_location_url) {
+ request.follow_redirect();
+ } else {
+ self.response = info.into();
+ }
+ }
+
+ fn on_response_started(
+ &mut self,
+ _: UrlRequestCallback,
+ req: UrlRequest,
+ info: UrlResponseInfo,
+ ) {
+ self.response = info.into();
+ self.read(req);
+ }
+
+ fn on_read_completed(
+ &mut self,
+ _: UrlRequestCallback,
+ req: UrlRequest,
+ _: UrlResponseInfo,
+ buffer: Buffer,
+ bytes_read: u64,
+ ) {
+ if bytes_read == 0 {
+ return;
+ }
+
+ let data = buffer.data_slice::(bytes_read as usize);
+ self.response.body_mut().as_bytes_mut().unwrap().put(data);
+
+ self.read(req);
+ }
+
+ fn on_succeeded(&mut self, _: UrlRequestCallback, req: UrlRequest, _: UrlResponseInfo) {
+ req.destroy();
+ let response = mem::take(&mut self.response);
+ self.tx.send(Status::Success(response)).unwrap();
+ }
+
+ fn on_failed(
+ &mut self,
+ _: UrlRequestCallback,
+ req: UrlRequest,
+ _: UrlResponseInfo,
+ error: CronetError,
+ ) {
+ req.destroy();
+ self.tx.send(Status::Error(error)).unwrap();
+ }
+
+ fn on_canceled(&mut self, _: UrlRequestCallback, req: UrlRequest, _: UrlResponseInfo) {
+ req.destroy();
+ self.tx.send(Status::Canceled).unwrap();
+ }
+}
diff --git a/src/date_time.rs b/src/date_time.rs
index f3bfc57..ada7bea 100644
--- a/src/date_time.rs
+++ b/src/date_time.rs
@@ -48,6 +48,12 @@ impl Destroy for DateTime {
}
}
+impl Default for DateTime {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
#[cfg(test)]
mod tests {
use std::time::UNIX_EPOCH;
diff --git a/src/engine.rs b/src/engine.rs
index c598370..b10bb4c 100644
--- a/src/engine.rs
+++ b/src/engine.rs
@@ -75,21 +75,21 @@ impl Engine {
}
/// A human-readable version string of the engine.
- pub fn version(&self) -> String {
+ pub fn version(&self) -> &str {
unsafe {
let version = Cronet_Engine_GetVersionString(self.ptr);
let version = CStr::from_ptr(version);
- version.to_string_lossy().into_owned()
+ version.to_str().unwrap()
}
}
/// Returns the default value of the `User-Agent` header.
/// Can be accessed before `StartWithParams()` is called.
- pub fn default_user_agent(&self) -> String {
+ pub fn default_user_agent(&self) -> &str {
unsafe {
let version = Cronet_Engine_GetDefaultUserAgent(self.ptr);
let version = CStr::from_ptr(version);
- version.to_string_lossy().into_owned()
+ version.to_str().unwrap()
}
}
@@ -110,6 +110,12 @@ impl Destroy for Engine {
}
}
+impl Default for Engine {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
#[cfg(test)]
mod tests {
use crate::Destroy;
diff --git a/src/engine_params.rs b/src/engine_params.rs
index 857e387..5863d84 100644
--- a/src/engine_params.rs
+++ b/src/engine_params.rs
@@ -57,12 +57,12 @@ impl EngineParams {
}
/// Returns the `User-Agent` header value.
- pub fn user_agent(&self) -> String {
+ pub fn user_agent(&self) -> &str {
unsafe {
let c_str = Cronet_EngineParams_user_agent_get(self.ptr);
let c_str = CStr::from_ptr(c_str);
let str_slice = c_str.to_str().unwrap();
- str_slice.to_owned()
+ str_slice
}
}
@@ -75,12 +75,12 @@ impl EngineParams {
}
/// Returns the `Accept-Language` header value.
- pub fn accept_language(&self) -> String {
+ pub fn accept_language(&self) -> &str {
unsafe {
let c_str = Cronet_EngineParams_accept_language_get(self.ptr);
let c_str = CStr::from_ptr(c_str);
let str_slice = c_str.to_str().unwrap();
- str_slice.to_owned()
+ str_slice
}
}
@@ -94,12 +94,12 @@ impl EngineParams {
}
/// Returns the directory for HTTP Cache and Prefs Storage.
- pub fn storage_path(&self) -> String {
+ pub fn storage_path(&self) -> &str {
unsafe {
let c_str = Cronet_EngineParams_storage_path_get(self.ptr);
let c_str = CStr::from_ptr(c_str);
let str_slice = c_str.to_str().unwrap();
- str_slice.to_owned()
+ str_slice
}
}
@@ -257,12 +257,12 @@ impl EngineParams {
}
}
- pub fn experimental_options(&self) -> String {
+ pub fn experimental_options(&self) -> &str {
unsafe {
let c_str = Cronet_EngineParams_experimental_options_get(self.ptr);
let c_str = CStr::from_ptr(c_str);
let str_slice = c_str.to_str().unwrap();
- str_slice.to_owned()
+ str_slice
}
}
}
@@ -273,6 +273,12 @@ impl Destroy for EngineParams {
}
}
+impl Default for EngineParams {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
#[derive(Debug, PartialEq)]
pub enum HttpCacheMode {
/// Disable HTTP cache.
diff --git a/src/error.rs b/src/error.rs
index b50a132..630b4b4 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -49,10 +49,10 @@ impl CronetError {
}
/// Get the error message.
- pub fn message(&self) -> String {
+ pub fn message(&self) -> &str {
unsafe {
let c_message = Cronet_Error_message_get(self.ptr);
- let message = CStr::from_ptr(c_message).to_string_lossy().into_owned();
+ let message = CStr::from_ptr(c_message).to_str().unwrap();
message
}
}
@@ -116,6 +116,12 @@ impl Destroy for CronetError {
}
}
+impl Default for CronetError {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
impl fmt::Display for CronetError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
diff --git a/src/executor.rs b/src/executor.rs
index 8eaf4ee..1fe9983 100644
--- a/src/executor.rs
+++ b/src/executor.rs
@@ -6,7 +6,7 @@ use crate::{
};
static mut EXECUTOR_CALLBACKS: Lazy> =
- Lazy::new(|| CronetCallbacks::new());
+ Lazy::new(CronetCallbacks::new);
#[no_mangle]
unsafe extern "C" fn cronetExecutorOnExecute(
diff --git a/src/http_header.rs b/src/http_header.rs
index 01d94de..9c4b6ae 100644
--- a/src/http_header.rs
+++ b/src/http_header.rs
@@ -20,12 +20,10 @@ impl HttpHeader {
}
/// Get the name of this header.
- pub fn name(&self) -> String {
+ pub fn name(&self) -> &'static str {
unsafe {
let c_name = Cronet_HttpHeader_name_get(self.ptr);
- let name = std::ffi::CStr::from_ptr(c_name)
- .to_string_lossy()
- .into_owned();
+ let name = std::ffi::CStr::from_ptr(c_name).to_str().unwrap();
name
}
}
@@ -38,10 +36,10 @@ impl HttpHeader {
}
}
- pub fn value(&self) -> String {
+ pub fn value(&self) -> &'static str {
unsafe {
let c_value = Cronet_HttpHeader_value_get(self.ptr);
- let value = CStr::from_ptr(c_value).to_string_lossy().into_owned();
+ let value = CStr::from_ptr(c_value).to_str().unwrap();
value
}
}
@@ -60,6 +58,12 @@ impl Destroy for HttpHeader {
}
}
+impl Default for HttpHeader {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
#[cfg(test)]
mod tests {
use crate::Destroy;
diff --git a/src/lib.rs b/src/lib.rs
index 6417583..2e51046 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -8,7 +8,7 @@ mod annotation;
mod buffer;
mod buffer_callback;
#[cfg(feature = "client")]
-mod client;
+pub mod client;
mod date_time;
mod destroy;
mod engine;
diff --git a/src/metrics.rs b/src/metrics.rs
index 155fa48..3da3ed8 100644
--- a/src/metrics.rs
+++ b/src/metrics.rs
@@ -161,24 +161,15 @@ impl Metrics {
}
pub fn socket_reused(&self) -> bool {
- unsafe {
- let reused = Cronet_Metrics_socket_reused_get(self.ptr);
- reused
- }
+ unsafe { Cronet_Metrics_socket_reused_get(self.ptr) }
}
pub fn sent_byte_count(&self) -> i64 {
- unsafe {
- let count = Cronet_Metrics_sent_byte_count_get(self.ptr);
- count
- }
+ unsafe { Cronet_Metrics_sent_byte_count_get(self.ptr) }
}
pub fn received_byte_count(&self) -> i64 {
- unsafe {
- let count = Cronet_Metrics_received_byte_count_get(self.ptr);
- count
- }
+ unsafe { Cronet_Metrics_received_byte_count_get(self.ptr) }
}
pub fn set_request_start(&self, datetime: DateTime) {
@@ -284,6 +275,12 @@ impl Destroy for Metrics {
}
}
+impl Default for Metrics {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
#[cfg(test)]
mod tests {
use std::time::SystemTime;
diff --git a/src/public_key_pins.rs b/src/public_key_pins.rs
index 2a2f537..6c26210 100644
--- a/src/public_key_pins.rs
+++ b/src/public_key_pins.rs
@@ -33,10 +33,10 @@ impl PublicKeyPins {
}
}
- pub fn host(&self) -> String {
+ pub fn host(&self) -> &str {
unsafe {
let c_str = Cronet_PublicKeyPins_host_get(self.ptr);
- let host = CStr::from_ptr(c_str).to_string_lossy().into_owned();
+ let host = CStr::from_ptr(c_str).to_str().unwrap();
host
}
}
@@ -58,10 +58,10 @@ impl PublicKeyPins {
unsafe { Cronet_PublicKeyPins_pins_sha256_size(self.ptr) }
}
- pub fn at(&self, index: u32) -> String {
+ pub fn at(&self, index: u32) -> &str {
unsafe {
let c_str = Cronet_PublicKeyPins_pins_sha256_at(self.ptr, index);
- CStr::from_ptr(c_str).to_string_lossy().into_owned()
+ CStr::from_ptr(c_str).to_str().unwrap()
}
}
@@ -111,6 +111,12 @@ impl Destroy for PublicKeyPins {
}
}
+impl Default for PublicKeyPins {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
#[cfg(test)]
mod tests {
use std::time::UNIX_EPOCH;
diff --git a/src/quic_hint.rs b/src/quic_hint.rs
index 53c52ad..a021548 100644
--- a/src/quic_hint.rs
+++ b/src/quic_hint.rs
@@ -28,10 +28,10 @@ impl QuicHint {
}
}
- pub fn host(&self) -> String {
+ pub fn host(&self) -> &str {
unsafe {
let c_str = Cronet_QuicHint_host_get(self.ptr);
- let host = CStr::from_ptr(c_str).to_string_lossy().into_owned();
+ let host = CStr::from_ptr(c_str).to_str().unwrap();
host
}
}
@@ -65,6 +65,12 @@ impl Destroy for QuicHint {
}
}
+impl Default for QuicHint {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
#[cfg(test)]
mod tests {
use crate::Destroy;
diff --git a/src/request_finished_info.rs b/src/request_finished_info.rs
index 8d3ddcf..3cc3123 100644
--- a/src/request_finished_info.rs
+++ b/src/request_finished_info.rs
@@ -87,6 +87,12 @@ impl Destroy for RequestFinishedInfo {
}
}
+impl Default for RequestFinishedInfo {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
/// Enum representing the reason why the request finished.
#[derive(Debug, PartialEq)]
pub enum RequestFinishedInfoReason {
diff --git a/src/request_finished_info_listener.rs b/src/request_finished_info_listener.rs
index e036e79..1f38676 100644
--- a/src/request_finished_info_listener.rs
+++ b/src/request_finished_info_listener.rs
@@ -10,7 +10,7 @@ use crate::{
static mut REQUEST_FINISHED_INFO_LISTENER_CALLBACKS: Lazy<
CronetCallbacks,
-> = Lazy::new(|| CronetCallbacks::new());
+> = Lazy::new(CronetCallbacks::new);
#[no_mangle]
unsafe extern "C" fn cronetOnRequestFinished(
@@ -50,10 +50,9 @@ impl RequestFinishedInfoListener {
}
}
- pub fn set_client_context(&self, raw_data: Cronet_RawDataPtr) {
- unsafe {
- Cronet_RequestFinishedInfoListener_SetClientContext(self.ptr, raw_data);
- }
+ #[allow(clippy::missing_safety_doc)]
+ pub unsafe fn set_client_context(&self, raw_data: Cronet_RawDataPtr) {
+ Cronet_RequestFinishedInfoListener_SetClientContext(self.ptr, raw_data);
}
}
@@ -84,7 +83,9 @@ mod tests {
#[test]
fn it_sets_client_context() {
let listener = super::RequestFinishedInfoListener::new(|_, _, _, _| {});
- listener.set_client_context(std::ptr::null_mut());
+ unsafe {
+ listener.set_client_context(std::ptr::null_mut());
+ }
listener.destroy();
}
}
diff --git a/src/runnable.rs b/src/runnable.rs
index bbe5e96..3a9e1d7 100644
--- a/src/runnable.rs
+++ b/src/runnable.rs
@@ -6,7 +6,7 @@ use crate::{
};
static mut RUNNABLE_CALLBACKS: Lazy> =
- Lazy::new(|| CronetCallbacks::new());
+ Lazy::new(CronetCallbacks::new);
#[no_mangle]
unsafe extern "C" fn cronetRunnableOnRun(selfPtr: Cronet_RunnablePtr) {
diff --git a/src/upload_data_provider.rs b/src/upload_data_provider.rs
index e632305..159276e 100644
--- a/src/upload_data_provider.rs
+++ b/src/upload_data_provider.rs
@@ -11,7 +11,7 @@ use crate::{
static mut UPLOAD_DATA_PROVIDER_CALLBACKS: Lazy<
CronetCallbacks>,
-> = Lazy::new(|| CronetCallbacks::new());
+> = Lazy::new(CronetCallbacks::new);
#[no_mangle]
unsafe extern "C" fn cronetUploadDataProviderGetLength(
@@ -19,7 +19,7 @@ unsafe extern "C" fn cronetUploadDataProviderGetLength(
) -> i64 {
let lockedMap = UPLOAD_DATA_PROVIDER_CALLBACKS.map().lock().unwrap();
let callback = lockedMap.get(&selfPtr).unwrap();
- return callback.length(UploadDataProvider { ptr: selfPtr });
+ callback.length(UploadDataProvider { ptr: selfPtr })
}
#[no_mangle]
@@ -105,8 +105,9 @@ impl UploadDataProvider {
}
}
- pub fn set_client_context(&self, client_context: Cronet_ClientContext) {
- unsafe { Cronet_UploadDataProvider_SetClientContext(self.ptr, client_context) }
+ #[allow(clippy::missing_safety_doc)]
+ pub unsafe fn set_client_context(&self, client_context: Cronet_ClientContext) {
+ Cronet_UploadDataProvider_SetClientContext(self.ptr, client_context)
}
pub fn client_context(&self) -> Cronet_ClientContext {
@@ -177,7 +178,7 @@ mod tests {
fn read(&self, _: UploadDataProvider, sink: UploadDataSink, buffer: Buffer) {
let size = buffer.size();
- sink.on_read_succeeded(size, true);
+ sink.on_read_succeeded(size, false);
}
fn rewind(&mut self, _: UploadDataProvider, sink: UploadDataSink) {
diff --git a/src/upload_data_sink.rs b/src/upload_data_sink.rs
index da90899..e8194f5 100644
--- a/src/upload_data_sink.rs
+++ b/src/upload_data_sink.rs
@@ -11,7 +11,7 @@ use crate::{
static mut UPLOAD_DATA_SINK_CALLBACKS: Lazy<
CronetCallbacks,
-> = Lazy::new(|| CronetCallbacks::new());
+> = Lazy::new(CronetCallbacks::new);
#[no_mangle]
unsafe extern "C" fn cronetUploadDataSinkOnReadSucceeded(
@@ -163,7 +163,7 @@ mod tests {
on_rewind_succeeded: |_| println!("on_rewind_succeeded"),
on_rewind_error: |_, _| println!("on_rewind_error"),
});
- upload_data_sink.on_read_succeeded(10, true);
+ upload_data_sink.on_read_succeeded(10, false);
upload_data_sink.on_rewind_succeeded();
upload_data_sink.on_read_error("error");
upload_data_sink.on_rewind_error("error");
diff --git a/src/url_request.rs b/src/url_request.rs
index 5544c6c..fd7bdf2 100644
--- a/src/url_request.rs
+++ b/src/url_request.rs
@@ -36,11 +36,11 @@ impl UrlRequest {
/// * `executor` - Executor on which all callbacks will be invoked.
pub fn init_with_params(
&self,
- engine: Engine,
+ engine: &Engine,
url: &str,
- params: UrlRequestParams,
- callback: UrlRequestCallback,
- executor: Executor,
+ params: &UrlRequestParams,
+ callback: &UrlRequestCallback,
+ executor: &Executor,
) -> EngineResult {
unsafe {
let c_str = CString::new(url).unwrap();
@@ -134,3 +134,9 @@ impl Destroy for UrlRequest {
}
}
}
+
+impl Default for UrlRequest {
+ fn default() -> Self {
+ Self::new()
+ }
+}
diff --git a/src/url_request_callback.rs b/src/url_request_callback.rs
index 846220f..0170164 100644
--- a/src/url_request_callback.rs
+++ b/src/url_request_callback.rs
@@ -11,7 +11,7 @@ use crate::{
static mut URL_REQUEST_CALLBACK_CALLBACKS: Lazy<
CronetCallbacks>,
-> = Lazy::new(|| CronetCallbacks::new());
+> = Lazy::new(CronetCallbacks::new);
#[no_mangle]
unsafe extern "C" fn cronetUrlRequestCallbackOnRedirectReceived(
@@ -20,8 +20,8 @@ unsafe extern "C" fn cronetUrlRequestCallbackOnRedirectReceived(
info_ptr: Cronet_UrlResponseInfoPtr,
new_location_url: Cronet_String,
) {
- let lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap();
- let callback = lockedMap.get(&self_ptr).unwrap();
+ let mut lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap();
+ let callback = lockedMap.get_mut(&self_ptr).unwrap();
let c_str = CStr::from_ptr(new_location_url);
let new_location_url = c_str.to_str().unwrap();
callback.on_redirect_received(
@@ -38,8 +38,8 @@ unsafe extern "C" fn cronetUrlRequestCallbackOnResponseStarted(
request_ptr: Cronet_UrlRequestPtr,
info_ptr: Cronet_UrlResponseInfoPtr,
) {
- let lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap();
- let callback = lockedMap.get(&self_ptr).unwrap();
+ let mut lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap();
+ let callback = lockedMap.get_mut(&self_ptr).unwrap();
callback.on_response_started(
UrlRequestCallback { ptr: self_ptr },
UrlRequest { ptr: request_ptr },
@@ -55,8 +55,8 @@ unsafe extern "C" fn cronetUrlRequestCallbackOnReadCompleted(
buffer_ptr: Cronet_BufferPtr,
bytes_read: u64,
) {
- let lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap();
- let callback = lockedMap.get(&self_ptr).unwrap();
+ let mut lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap();
+ let callback = lockedMap.get_mut(&self_ptr).unwrap();
callback.on_read_completed(
UrlRequestCallback { ptr: self_ptr },
UrlRequest { ptr: request_ptr },
@@ -72,8 +72,8 @@ unsafe extern "C" fn cronetUrlRequestCallbackOnSucceeded(
request_ptr: Cronet_UrlRequestPtr,
info_ptr: Cronet_UrlResponseInfoPtr,
) {
- let lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap();
- let callback = lockedMap.get(&self_ptr).unwrap();
+ let mut lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap();
+ let callback = lockedMap.get_mut(&self_ptr).unwrap();
callback.on_succeeded(
UrlRequestCallback { ptr: self_ptr },
UrlRequest { ptr: request_ptr },
@@ -88,8 +88,8 @@ unsafe extern "C" fn cronetUrlRequestCallbackOnFailed(
info_ptr: Cronet_UrlResponseInfoPtr,
error_ptr: Cronet_ErrorPtr,
) {
- let lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap();
- let callback = lockedMap.get(&self_ptr).unwrap();
+ let mut lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap();
+ let callback = lockedMap.get_mut(&self_ptr).unwrap();
callback.on_failed(
UrlRequestCallback { ptr: self_ptr },
UrlRequest { ptr: request_ptr },
@@ -104,8 +104,8 @@ unsafe extern "C" fn cronetUrlRequestCallbackOnCanceled(
request_ptr: Cronet_UrlRequestPtr,
info_ptr: Cronet_UrlResponseInfoPtr,
) {
- let lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap();
- let callback = lockedMap.get(&self_ptr).unwrap();
+ let mut lockedMap = URL_REQUEST_CALLBACK_CALLBACKS.map().lock().unwrap();
+ let callback = lockedMap.get_mut(&self_ptr).unwrap();
callback.on_canceled(
UrlRequestCallback { ptr: self_ptr },
UrlRequest { ptr: request_ptr },
@@ -168,7 +168,7 @@ pub trait UrlRequestCallbackHandler {
/// * `info`: Response information.
/// * `newLocationUrl`: Location where the request is redirected.
fn on_redirect_received(
- &self,
+ &mut self,
url_request_callback: UrlRequestCallback,
request: UrlRequest,
info: UrlResponseInfo,
@@ -189,7 +189,7 @@ pub trait UrlRequestCallbackHandler {
/// * `request`: Request that started to get the response.
/// * `info`: Response information.
fn on_response_started(
- &self,
+ &mut self,
url_request_callback: UrlRequestCallback,
request: UrlRequest,
info: UrlResponseInfo,
@@ -214,7 +214,7 @@ pub trait UrlRequestCallbackHandler {
/// containing the received data.
/// * `bytesRead`: The number of bytes read into the `buffer`.
fn on_read_completed(
- &self,
+ &mut self,
url_request_callback: UrlRequestCallback,
request: UrlRequest,
info: UrlResponseInfo,
@@ -233,7 +233,7 @@ pub trait UrlRequestCallbackHandler {
/// * `request`: Request that succeeded.
/// * `info`: Response information. NOTE: this is owned by the request.
fn on_succeeded(
- &self,
+ &mut self,
url_request_callback: UrlRequestCallback,
request: UrlRequest,
info: UrlResponseInfo,
@@ -252,7 +252,7 @@ pub trait UrlRequestCallbackHandler {
/// * `info`: Response information. May be `None` if no response was received. NOTE: this is owned by the request.
/// * `error`: Information about the error. NOTE: this is owned by the request.
fn on_failed(
- &self,
+ &mut self,
url_request_callback: UrlRequestCallback,
request: UrlRequest,
info: UrlResponseInfo,
@@ -270,7 +270,7 @@ pub trait UrlRequestCallbackHandler {
/// * `request`: Request that was canceled.
/// * `info`: Response information. May be `None` if no response was received. NOTE: this is owned by the request.
fn on_canceled(
- &self,
+ &mut self,
url_request_callback: UrlRequestCallback,
request: UrlRequest,
info: UrlResponseInfo,
@@ -287,7 +287,7 @@ mod tests {
impl UrlRequestCallbackHandler for TestUrlRequestCallbackHandler {
fn on_redirect_received(
- &self,
+ &mut self,
_: UrlRequestCallback,
_: UrlRequest,
_: UrlResponseInfo,
@@ -296,10 +296,17 @@ mod tests {
println!("on_redirect_received");
}
- fn on_response_started(&self, _: UrlRequestCallback, _: UrlRequest, _: UrlResponseInfo) {}
+ fn on_response_started(
+ &mut self,
+ _: UrlRequestCallback,
+ _: UrlRequest,
+ _: UrlResponseInfo,
+ ) {
+ println!("on_response_started")
+ }
fn on_read_completed(
- &self,
+ &mut self,
_: UrlRequestCallback,
_: UrlRequest,
_: UrlResponseInfo,
@@ -309,10 +316,12 @@ mod tests {
println!("on_read_completed");
}
- fn on_succeeded(&self, _: UrlRequestCallback, _: UrlRequest, _: UrlResponseInfo) {}
+ fn on_succeeded(&mut self, _: UrlRequestCallback, _: UrlRequest, _: UrlResponseInfo) {
+ println!("on_succeeded");
+ }
fn on_failed(
- &self,
+ &mut self,
_: UrlRequestCallback,
_: UrlRequest,
_: UrlResponseInfo,
@@ -321,7 +330,7 @@ mod tests {
println!("on_failed");
}
- fn on_canceled(&self, _: UrlRequestCallback, _: UrlRequest, _: UrlResponseInfo) {
+ fn on_canceled(&mut self, _: UrlRequestCallback, _: UrlRequest, _: UrlResponseInfo) {
println!("on_canceled");
}
}
diff --git a/src/url_request_params.rs b/src/url_request_params.rs
index f972b24..da8304d 100644
--- a/src/url_request_params.rs
+++ b/src/url_request_params.rs
@@ -53,12 +53,12 @@ impl UrlRequestParams {
}
}
- pub fn method(&self) -> String {
+ pub fn method(&self) -> &str {
unsafe {
let c_str = Cronet_UrlRequestParams_http_method_get(self.ptr);
let c_str = CStr::from_ptr(c_str);
let str_slice = c_str.to_str().unwrap();
- str_slice.to_owned()
+ str_slice
}
}
@@ -270,6 +270,12 @@ impl Destroy for UrlRequestParams {
}
}
+impl Default for UrlRequestParams {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
#[cfg(feature = "client")]
impl From> for UrlRequestParams
where
diff --git a/src/url_request_status_listener.rs b/src/url_request_status_listener.rs
index 3eae5d5..9dd3097 100644
--- a/src/url_request_status_listener.rs
+++ b/src/url_request_status_listener.rs
@@ -8,7 +8,7 @@ use crate::{
static mut URL_REQUEST_STATUS_LISTENER_CALLBACKS: Lazy<
CronetCallbacks,
-> = Lazy::new(|| CronetCallbacks::new());
+> = Lazy::new(CronetCallbacks::new);
#[no_mangle]
unsafe extern "C" fn cronetUrlRequestStatusListenerOnStatus(
@@ -53,6 +53,12 @@ impl Destroy for UrlRequestStatusListener {
}
}
+impl Default for UrlRequestStatusListener {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
/// Enum representing the status of a [crate::UrlRequest].
#[derive(Debug, PartialEq)]
pub enum UrlRequestStatus {
diff --git a/src/url_response_info.rs b/src/url_response_info.rs
index 4037722..ccff671 100644
--- a/src/url_response_info.rs
+++ b/src/url_response_info.rs
@@ -1,5 +1,7 @@
use std::ffi::{CStr, CString};
+use http::{HeaderValue, Response, StatusCode, Version};
+
use crate::{
Cronet_UrlResponseInfoPtr, Cronet_UrlResponseInfo_Create, Cronet_UrlResponseInfo_Destroy,
Cronet_UrlResponseInfo_all_headers_list_add, Cronet_UrlResponseInfo_all_headers_list_at,
@@ -31,11 +33,11 @@ impl UrlResponseInfo {
/// The URL the response is for.
/// This is the URL after following redirects, so it may not be the originally requested URL
- pub fn url(&self) -> String {
+ pub fn url(&self) -> &str {
unsafe {
let url = Cronet_UrlResponseInfo_url_get(self.ptr);
let url = CStr::from_ptr(url);
- url.to_string_lossy().into_owned()
+ url.to_str().unwrap()
}
}
@@ -54,11 +56,11 @@ impl UrlResponseInfo {
/// The URL at the given index in the chain.
/// The first entry is the originally requested URL; the following entries are redirects followed.
- pub fn url_chain_at(&self, index: u32) -> String {
+ pub fn url_chain_at(&self, index: u32) -> &str {
unsafe {
let url = Cronet_UrlResponseInfo_url_chain_at(self.ptr, index);
let url = CStr::from_ptr(url);
- url.to_string_lossy().into_owned()
+ url.to_str().unwrap()
}
}
@@ -91,11 +93,11 @@ impl UrlResponseInfo {
/// The HTTP status text of the status line.
/// For example, if the request received a "HTTP/1.1 200 OK" response, this method returns "OK".
- pub fn status_text(&self) -> String {
+ pub fn status_text(&self) -> &str {
unsafe {
let text = Cronet_UrlResponseInfo_http_status_text_get(self.ptr);
let text = CStr::from_ptr(text);
- text.to_string_lossy().into_owned()
+ text.to_str().unwrap()
}
}
@@ -107,10 +109,7 @@ impl UrlResponseInfo {
}
pub fn header_size(&self) -> u32 {
- unsafe {
- let size = Cronet_UrlResponseInfo_all_headers_list_size(self.ptr);
- size
- }
+ unsafe { Cronet_UrlResponseInfo_all_headers_list_size(self.ptr) }
}
pub fn header_at(&self, index: u32) -> HttpHeader {
@@ -146,11 +145,12 @@ impl UrlResponseInfo {
/// The protocol (for example 'quic/1+spdy/3') negotiated with the server.
/// An empty string if no protocol was negotiated, the protocol is
/// not known, or when using plain HTTP or HTTPS.
- pub fn negotiated_protocol(&self) -> String {
+ pub fn negotiated_protocol(&self) -> &'static str {
unsafe {
let protocol = Cronet_UrlResponseInfo_negotiated_protocol_get(self.ptr);
let protocol = CStr::from_ptr(protocol);
- protocol.to_string_lossy().into_owned()
+ let protocol = protocol.to_str().unwrap();
+ protocol
}
}
@@ -162,11 +162,11 @@ impl UrlResponseInfo {
}
/// The proxy server that was used for the request.
- pub fn proxy_server(&self) -> String {
+ pub fn proxy_server(&self) -> &'static str {
unsafe {
let server = Cronet_UrlResponseInfo_proxy_server_get(self.ptr);
- let server = CStr::from_ptr(server);
- server.to_string_lossy().into_owned()
+ let server = CStr::from_ptr(server).to_str().unwrap();
+ server
}
}
@@ -197,6 +197,52 @@ impl Destroy for UrlResponseInfo {
}
}
+impl Default for UrlResponseInfo {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+#[cfg(feature = "client")]
+#[allow(clippy::from_over_into)]
+impl Into> for UrlResponseInfo
+where
+ T: Default,
+{
+ fn into(self) -> Response {
+ let mut response = Response::default();
+
+ // Set HTTP version
+ let version = match self.negotiated_protocol() {
+ "http/0.9" => Version::HTTP_09,
+ "http/1.0" => Version::HTTP_10,
+ "http/1.1" => Version::HTTP_11,
+ "h2" => Version::HTTP_2,
+ "h3" => Version::HTTP_3,
+ "" => Version::HTTP_11,
+ version => panic!("Server responded with unknown HTTP version '{}'", version),
+ };
+ *response.version_mut() = version;
+
+ // Set status code
+ let status_code = self.status_code();
+ *response.status_mut() = StatusCode::from_u16(status_code as u16).unwrap();
+
+ // Set headers
+ let header_size = self.header_size();
+ for i in 0..header_size {
+ let header = self.header_at(i);
+ let name = header.name();
+ let value = header.value();
+ response
+ .headers_mut()
+ .insert(name, HeaderValue::from_static(value));
+ }
+
+ response
+ }
+}
+
#[cfg(test)]
mod tests {
use crate::Destroy;