use crate::VersionNumber;
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub struct Quirks {
pub accept_unencoded_token: bool,
pub send_unencoded_token: bool,
pub omit_routing_headers: bool,
pub case_insensitive_module_ids: bool,
pub peer_max_page_limit: Option<u64>,
pub lenient_content_type: bool,
}
impl Default for Quirks {
fn default() -> Self {
Self {
accept_unencoded_token: false,
send_unencoded_token: false,
omit_routing_headers: false,
case_insensitive_module_ids: true,
peer_max_page_limit: None,
lenient_content_type: false,
}
}
}
impl Quirks {
#[must_use]
pub fn strict() -> Self {
Self { case_insensitive_module_ids: false, ..Self::default() }
}
#[must_use]
pub fn permissive() -> Self {
Self {
accept_unencoded_token: true,
case_insensitive_module_ids: true,
lenient_content_type: true,
send_unencoded_token: false,
omit_routing_headers: false,
peer_max_page_limit: None,
}
}
#[must_use]
pub fn for_version(version: &VersionNumber) -> Self {
let mut quirks = Self::default();
if matches!(
version,
VersionNumber::V2_0 | VersionNumber::V2_1 | VersionNumber::V2_1_1 | VersionNumber::V2_2
) {
quirks.accept_unencoded_token = true;
quirks.send_unencoded_token = true;
}
if !version.has_routing_headers() {
quirks.omit_routing_headers = true;
}
quirks
}
#[must_use]
pub fn with_peer_max_page_limit(mut self, limit: u64) -> Self {
self.peer_max_page_limit = Some(limit);
self
}
#[must_use]
pub fn effective_limit(&self, requested: Option<u64>) -> Option<u64> {
match (requested, self.peer_max_page_limit) {
(Some(r), Some(max)) => Some(r.min(max)),
(Some(r), None) => Some(r),
(None, max) => max,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn defaults_are_conformant_not_permissive() {
let q = Quirks::default();
assert!(!q.accept_unencoded_token, "2.2-d2 and later require Base64");
assert!(!q.send_unencoded_token);
assert!(!q.omit_routing_headers);
assert!(!q.lenient_content_type);
assert!(q.case_insensitive_module_ids);
}
#[test]
fn legacy_versions_get_exactly_the_relaxations_they_need() {
let v211 = Quirks::for_version(&VersionNumber::V2_1_1);
assert!(v211.accept_unencoded_token && v211.send_unencoded_token);
assert!(v211.omit_routing_headers);
let v22 = Quirks::for_version(&VersionNumber::V2_2);
assert!(v22.accept_unencoded_token, "2.2 predates the Base64 requirement");
assert!(!v22.omit_routing_headers, "2.2 introduced routing headers");
let v221 = Quirks::for_version(&VersionNumber::V2_2_1);
assert!(!v221.accept_unencoded_token);
assert!(!v221.omit_routing_headers);
}
#[test]
fn page_limits_are_clamped_to_what_the_peer_tolerates() {
let q = Quirks::default().with_peer_max_page_limit(100);
assert_eq!(q.effective_limit(Some(2000)), Some(100));
assert_eq!(q.effective_limit(Some(10)), Some(10));
assert_eq!(q.effective_limit(None), Some(100));
assert_eq!(Quirks::default().effective_limit(None), None);
}
#[test]
fn the_strict_profile_accommodates_nothing() {
let q = Quirks::strict();
assert!(!q.case_insensitive_module_ids);
assert!(!q.accept_unencoded_token && !q.lenient_content_type);
}
}