#[cfg(doctest)]
#[doc = include_str!("../README.md")]
struct ReadmeDoctests;
#[macro_use]
pub mod macros;
pub mod capacity;
pub mod client;
pub mod config;
pub mod error;
mod fetch;
pub mod health;
pub mod hold;
pub mod hooks;
mod query;
pub mod rate_limit;
pub mod request;
pub mod response;
pub mod send;
pub mod transport;
#[cfg(feature = "keychain")]
pub mod keychain;
#[cfg(test)]
mod macro_tests;
const LOG_BODY_MAX_LEN: usize = 512;
pub fn truncate_for_log(s: &str) -> std::borrow::Cow<'_, str> {
if s.len() <= LOG_BODY_MAX_LEN {
std::borrow::Cow::Borrowed(s)
} else {
let truncated = &s[..s.floor_char_boundary(LOG_BODY_MAX_LEN)];
std::borrow::Cow::Owned(format!("{}... [truncated]", truncated))
}
}
pub use http;
#[doc(hidden)]
pub use polyoxide_rt as __rt;
#[cfg(not(target_arch = "wasm32"))]
pub use reqwest;
pub use capacity::CapacityBucket;
pub use client::{
retry_after_header, HttpClient, HttpClientBuilder, DEFAULT_POOL_SIZE, DEFAULT_TIMEOUT_MS,
};
pub use config::ClientConfig;
pub use error::{ApiError, ErrorResponse};
#[cfg(target_arch = "wasm32")]
pub use fetch::FetchTransport;
pub use health::Pong;
pub use hold::Hold;
pub use hooks::{
AttemptInfo, Authenticator, Charge, Cost, Decision, DefaultRetryPolicy, DynAuthenticator,
DynRetryPolicy, DynThrottle, LayerCharge, LayerId, NoThrottle, Outcome, Refused, RequestMeta,
RequestParts, ResponseMeta, RetryPolicy, Throttle,
};
pub use query::csv;
pub use rate_limit::{
BucketId, EffectiveQuota, Matching, QuotaRow, RateLimiter, RetryConfig, WindowQuotaTable,
};
pub use request::{QueryBuilder, Request, RequestError};
pub use response::Response;
pub use send::decode_json;
#[cfg(not(target_arch = "wasm32"))]
pub use transport::ReqwestTransport;
pub use transport::{HttpRequest, HttpTransport, TransportError, TransportKind};
#[cfg(feature = "keychain")]
pub use keychain::KeychainError;
const _: fn() = || {
fn is<T: polyoxide_venue::Classify>() {}
is::<ApiError>();
is::<Refused>();
is::<TransportError>();
#[cfg(feature = "keychain")]
is::<KeychainError>();
};
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_http_vocabulary_is_the_type_reqwest_sends() {
let method: crate::reqwest::Method = crate::http::Method::POST;
let status: crate::reqwest::StatusCode = crate::http::StatusCode::TOO_MANY_REQUESTS;
let mut headers: crate::reqwest::header::HeaderMap = crate::http::HeaderMap::new();
headers.insert(
crate::http::header::RETRY_AFTER,
crate::http::HeaderValue::from_static("3"),
);
assert_eq!(method, crate::reqwest::Method::POST);
assert_eq!(status.as_u16(), 429);
assert_eq!(
headers[crate::reqwest::header::RETRY_AFTER]
.to_str()
.unwrap(),
"3"
);
}
#[test]
fn test_truncate_for_log_short_string_unchanged() {
let short = "hello world";
let result = truncate_for_log(short);
assert_eq!(result.as_ref(), short);
}
#[test]
fn test_truncate_for_log_exact_limit_unchanged() {
let exact = "a".repeat(LOG_BODY_MAX_LEN);
let result = truncate_for_log(&exact);
assert_eq!(result.as_ref(), exact.as_str());
}
#[test]
fn test_truncate_for_log_over_limit_truncated() {
let long = "x".repeat(LOG_BODY_MAX_LEN + 100);
let result = truncate_for_log(&long);
assert!(result.ends_with("... [truncated]"));
assert!(result.len() < long.len());
}
#[test]
fn test_truncate_for_log_multibyte_char_boundary() {
let mut s = "a".repeat(LOG_BODY_MAX_LEN - 1);
s.push('\u{1F600}'); s.push_str("overflow");
let result = truncate_for_log(&s);
assert!(result.ends_with("... [truncated]"));
assert!(result.is_char_boundary(0));
}
}