fetchttp 1.0.1

`fetch` Web API Implementation In Rust!
Documentation
//! IAI-Callgrind benchmarks for instruction counting and cache analysis

use fetchttp::*;
use iai_callgrind::{
    library_benchmark, library_benchmark_group, main, EventKind, FlamegraphConfig,
    LibraryBenchmarkConfig, RegressionConfig, Tool, ValgrindTool,
};

#[library_benchmark]
fn headers_create() -> Headers {
    Headers::new()
}

#[library_benchmark]
fn headers_set_single() -> Headers {
    let mut headers = Headers::new();
    headers.set("content-type", "application/json").unwrap();
    headers
}

#[library_benchmark]
fn headers_set_multiple() -> Headers {
    let mut headers = Headers::new();
    headers.set("content-type", "application/json").unwrap();
    headers.set("accept", "application/json").unwrap();
    headers.set("user-agent", "fetchttp/0.1.0").unwrap();
    headers.set("authorization", "Bearer token").unwrap();
    headers.set("x-custom", "value").unwrap();
    headers
}

#[library_benchmark]
fn headers_get() -> Option<String> {
    let mut headers = Headers::new();
    headers.set("content-type", "application/json").unwrap();
    headers.get("content-type").unwrap()
}

#[library_benchmark]
fn headers_has() -> bool {
    let mut headers = Headers::new();
    headers.set("content-type", "application/json").unwrap();
    headers.has("content-type").unwrap()
}

#[library_benchmark]
fn headers_append() -> Headers {
    let mut headers = Headers::new();
    headers.set("accept", "application/json").unwrap();
    headers.append("accept", "text/plain").unwrap();
    headers
}

#[library_benchmark]
fn headers_validation_success() -> Headers {
    let mut headers = Headers::new();
    headers.set("x-custom-header", "valid-value").unwrap();
    headers
}

#[library_benchmark]
fn headers_validation_failure() {
    let mut headers = Headers::new();
    let _ = headers.set("", "value");
}

#[library_benchmark]
fn body_create_text() -> ReadableStream {
    ReadableStream::from_text("Hello, World!")
}

#[library_benchmark]
fn body_create_bytes() -> ReadableStream {
    let data = vec![0u8; 1024];
    ReadableStream::from_bytes(bytes::Bytes::from(data))
}

#[library_benchmark]
fn body_create_json() -> ReadableStream {
    let value = serde_json::json!({"key": "value", "number": 42});
    ReadableStream::from_json(&value)
}

#[library_benchmark]
fn body_create_large_text() -> ReadableStream {
    let large_text = "x".repeat(10240); // 10KB
    ReadableStream::from_text(&large_text)
}

#[library_benchmark]
fn body_create_large_bytes() -> ReadableStream {
    let data = vec![0u8; 10240]; // 10KB
    ReadableStream::from_bytes(bytes::Bytes::from(data))
}

#[library_benchmark]
fn request_create_simple() -> Request {
    Request::new("https://example.com", None).unwrap()
}

#[library_benchmark]
fn request_create_with_headers() -> Request {
    let mut headers = Headers::new();
    headers.set("content-type", "application/json").unwrap();
    headers.set("accept", "application/json").unwrap();

    let mut init = RequestInit::new();
    init.headers = Some(headers);

    Request::new("https://example.com", Some(init)).unwrap()
}

#[library_benchmark]
fn request_create_with_body() -> Request {
    let mut init = RequestInit::new();
    init.method = Some("POST".to_string());
    init.body = Some(ReadableStream::from_text("test body"));

    Request::new("https://example.com", Some(init)).unwrap()
}

#[library_benchmark]
fn request_create_full_init() -> Request {
    let mut headers = Headers::new();
    headers.set("content-type", "application/json").unwrap();
    headers.set("accept", "application/json").unwrap();
    headers.set("user-agent", "fetchttp/0.1.0").unwrap();
    headers.set("authorization", "Bearer token").unwrap();

    let mut init = RequestInit::new();
    init.method = Some("POST".to_string());
    init.headers = Some(headers);
    init.body = Some(ReadableStream::from_text("test body"));
    init.mode = Some(RequestMode::Cors);
    init.credentials = Some(RequestCredentials::Include);
    init.cache = Some(RequestCache::NoCache);
    init.redirect = Some(RequestRedirect::Follow);

    Request::new("https://example.com/api/v1/users", Some(init)).unwrap()
}

#[library_benchmark]
fn request_method_validation_success() -> Request {
    let mut init = RequestInit::new();
    init.method = Some("POST".to_string());
    Request::new("https://example.com", Some(init)).unwrap()
}

#[library_benchmark]
fn request_method_validation_failure() {
    let mut init = RequestInit::new();
    init.method = Some("".to_string());
    let _ = Request::new("https://example.com", Some(init));
}

#[library_benchmark]
fn request_url_validation_success() -> Request {
    Request::new("https://example.com/path?query=value#fragment", None).unwrap()
}

#[library_benchmark]
fn request_url_validation_failure() {
    let _ = Request::new("not-a-valid-url", None);
}

#[library_benchmark]
fn response_create_simple() -> Response {
    Response::new(None, None).unwrap()
}

#[library_benchmark]
fn response_create_with_headers() -> Response {
    let mut headers = Headers::new();
    headers.set("content-type", "application/json").unwrap();
    headers.set("x-custom", "value").unwrap();

    let mut init = ResponseInit::new();
    init.headers = Some(headers);

    Response::new(None, Some(init)).unwrap()
}

#[library_benchmark]
fn response_create_with_body() -> Response {
    let body = ReadableStream::from_text("response body");
    Response::new(Some(body), None).unwrap()
}

#[library_benchmark]
fn response_create_full() -> Response {
    let mut headers = Headers::new();
    headers.set("content-type", "application/json").unwrap();
    headers.set("cache-control", "no-cache").unwrap();
    headers.set("x-custom", "value").unwrap();

    let mut init = ResponseInit::new();
    init.status = Some(201);
    init.status_text = Some("Created".to_string());
    init.headers = Some(headers);

    let body = ReadableStream::from_json(&serde_json::json!({"status": "created"}));
    Response::new(Some(body), Some(init)).unwrap()
}

#[library_benchmark]
fn response_error() -> Response {
    Response::error()
}

#[library_benchmark]
fn response_redirect() -> Response {
    Response::redirect("https://example.com/new-location", Some(302)).unwrap()
}

#[library_benchmark]
fn response_status_validation_success() -> Response {
    let mut init = ResponseInit::new();
    init.status = Some(404);
    Response::new(None, Some(init)).unwrap()
}

#[library_benchmark]
fn response_status_validation_failure() {
    let mut init = ResponseInit::new();
    init.status = Some(600);
    let _ = Response::new(None, Some(init));
}

#[library_benchmark]
fn abort_signal_create() -> AbortSignal {
    AbortSignal::new()
}

#[library_benchmark]
fn abort_signal_abort() -> AbortSignal {
    AbortSignal::abort(Some("Test abort".to_string()))
}

#[library_benchmark]
fn abort_controller_create() -> AbortController {
    AbortController::new()
}

#[library_benchmark]
fn abort_controller_abort() -> AbortController {
    let controller = AbortController::new();
    controller.abort();
    controller
}

#[library_benchmark]
fn json_serialization_small() -> ReadableStream {
    let value = serde_json::json!({"key": "value"});
    ReadableStream::from_json(&value)
}

#[library_benchmark]
fn json_serialization_medium() -> ReadableStream {
    let value = serde_json::json!({
        "users": [
            {"id": 1, "name": "Alice", "email": "alice@example.com"},
            {"id": 2, "name": "Bob", "email": "bob@example.com"},
            {"id": 3, "name": "Charlie", "email": "charlie@example.com"}
        ],
        "metadata": {
            "total": 3,
            "page": 1,
            "per_page": 10
        }
    });
    ReadableStream::from_json(&value)
}

#[library_benchmark]
fn json_serialization_large() -> ReadableStream {
    let mut users = Vec::new();
    for i in 0..1000 {
        users.push(serde_json::json!({
            "id": i,
            "name": format!("User {}", i),
            "email": format!("user{}@example.com", i),
            "created_at": "2025-06-04T09:59:14Z",
            "updated_at": "2025-06-04T09:59:14Z"
        }));
    }

    let value = serde_json::json!({
        "users": users,
        "metadata": {
            "total": 1000,
            "page": 1,
            "per_page": 1000
        }
    });
    ReadableStream::from_json(&value)
}

#[library_benchmark]
fn clone_operations() -> (Request, Response) {
    let request = Request::new("https://example.com", None).unwrap();
    let response = Response::new(None, None).unwrap();

    let cloned_request = request.clone_request().unwrap();
    let cloned_response = response.clone_response().unwrap();

    (cloned_request, cloned_response)
}

library_benchmark_group!(
    name = headers_bench;
    benchmarks =
        headers_create,
        headers_set_single,
        headers_set_multiple,
        headers_get,
        headers_has,
        headers_append,
        headers_validation_success,
        headers_validation_failure
);

library_benchmark_group!(
    name = body_bench;
    benchmarks =
        body_create_text,
        body_create_bytes,
        body_create_json,
        body_create_large_text,
        body_create_large_bytes
);

library_benchmark_group!(
    name = request_bench;
    benchmarks =
        request_create_simple,
        request_create_with_headers,
        request_create_with_body,
        request_create_full_init,
        request_method_validation_success,
        request_method_validation_failure,
        request_url_validation_success,
        request_url_validation_failure
);

library_benchmark_group!(
    name = response_bench;
    benchmarks =
        response_create_simple,
        response_create_with_headers,
        response_create_with_body,
        response_create_full,
        response_error,
        response_redirect,
        response_status_validation_success,
        response_status_validation_failure
);

library_benchmark_group!(
    name = abort_bench;
    benchmarks =
        abort_signal_create,
        abort_signal_abort,
        abort_controller_create,
        abort_controller_abort
);

library_benchmark_group!(
    name = serialization_bench;
    benchmarks =
        json_serialization_small,
        json_serialization_medium,
        json_serialization_large
);

library_benchmark_group!(
    name = misc_bench;
    benchmarks =
        clone_operations
);

main!(
    config = LibraryBenchmarkConfig::default()
                .tool(Tool::new(ValgrindTool::DHAT))
                .tool(Tool::new(ValgrindTool::Massif))
                .tool(Tool::new(ValgrindTool::BBV))
                .tool(Tool::new(ValgrindTool::Memcheck))
                .tool(Tool::new(ValgrindTool::Helgrind))
                .tool(Tool::new(ValgrindTool::DRD))
                .flamegraph(FlamegraphConfig::default())
                .regression(
                    RegressionConfig::default()
                    .limits([(EventKind::Ir, 5.0)])
                    );
    library_benchmark_groups =
        headers_bench,
        body_bench,
        request_bench,
        response_bench,
        abort_bench,
        serialization_bench,
        misc_bench
);