#![allow(
clippy::approx_constant,
clippy::useless_vec,
clippy::len_zero,
clippy::unnecessary_cast,
clippy::redundant_closure,
clippy::too_many_arguments,
clippy::type_complexity,
clippy::needless_borrow,
clippy::enum_variant_names,
clippy::upper_case_acronyms,
clippy::inconsistent_digit_grouping,
clippy::unit_cmp,
clippy::assertions_on_constants,
clippy::iter_on_single_items,
clippy::expect_fun_call,
clippy::redundant_pattern_matching,
variant_size_differences,
clippy::absurd_extreme_comparisons,
clippy::nonminimal_bool,
clippy::for_kv_map,
clippy::needless_range_loop,
clippy::single_match,
clippy::collapsible_if,
clippy::needless_return,
clippy::redundant_clone,
clippy::map_entry,
clippy::match_single_binding,
clippy::bool_comparison,
clippy::derivable_impls,
clippy::manual_range_contains,
clippy::needless_borrows_for_generic_args,
clippy::manual_map,
clippy::vec_init_then_push,
clippy::identity_op,
clippy::manual_flatten,
clippy::single_char_pattern,
clippy::search_is_some,
clippy::option_map_unit_fn,
clippy::while_let_on_iterator,
clippy::clone_on_copy,
clippy::box_collection,
clippy::redundant_field_names,
clippy::ptr_arg,
clippy::large_enum_variant,
clippy::match_ref_pats,
clippy::needless_pass_by_value,
clippy::unused_unit,
clippy::let_and_return,
clippy::suspicious_else_formatting,
clippy::manual_strip,
clippy::match_like_matches_macro,
clippy::from_over_into,
clippy::wrong_self_convention,
clippy::inherent_to_string,
clippy::new_without_default,
clippy::unnecessary_wraps,
clippy::field_reassign_with_default,
clippy::manual_find,
clippy::unnecessary_lazy_evaluations,
clippy::should_implement_trait,
clippy::missing_safety_doc,
clippy::unusual_byte_groupings,
clippy::bool_assert_comparison,
clippy::zero_prefixed_literal,
clippy::await_holding_lock,
clippy::manual_saturating_arithmetic,
clippy::explicit_counter_loop,
clippy::needless_lifetimes,
clippy::single_component_path_imports,
clippy::uninlined_format_args,
clippy::iter_cloned_collect,
clippy::manual_str_repeat,
clippy::excessive_precision,
clippy::precedence,
clippy::unnecessary_literal_unwrap
)]
use std::collections::BTreeMap;
use oxicode::{
config, decode_from_slice, decode_from_slice_with_config, encode_to_vec,
encode_to_vec_with_config,
};
#[test]
fn test_string_empty_roundtrip() {
let s = String::new();
let encoded = encode_to_vec(&s).expect("encode empty String failed");
assert_eq!(
encoded.len(),
1,
"empty string must encode to exactly 1 byte"
);
assert_eq!(encoded[0], 0x00, "first byte must be 0x00 for length 0");
let (decoded, _): (String, _) =
decode_from_slice(&encoded).expect("decode empty String failed");
assert_eq!(decoded, "");
}
#[test]
fn test_string_single_ascii_char_roundtrip() {
let s = "a".to_string();
let encoded = encode_to_vec(&s).expect("encode single-char string failed");
assert_eq!(
encoded.len(),
2,
"single-char ASCII string must encode to 2 bytes"
);
assert_eq!(encoded[0], 0x01);
assert_eq!(encoded[1], b'a');
let (decoded, _): (String, _) =
decode_from_slice(&encoded).expect("decode single-char string failed");
assert_eq!(decoded, s);
}
#[test]
fn test_string_250_bytes_roundtrip() {
let s = "x".repeat(250);
let encoded = encode_to_vec(&s).expect("encode 250-byte string failed");
assert_eq!(
encoded.len(),
251,
"250-byte string must encode to 251 bytes (1 length + 250 content)"
);
assert_eq!(encoded[0], 250, "varint(250) must be a single byte 250");
let (decoded, _): (String, _) =
decode_from_slice(&encoded).expect("decode 250-byte string failed");
assert_eq!(decoded, s);
}
#[test]
fn test_string_251_bytes_roundtrip() {
let s = "y".repeat(251);
let encoded = encode_to_vec(&s).expect("encode 251-byte string failed");
assert_eq!(
encoded.len(),
254,
"251-byte string must encode to 254 bytes (3 length + 251 content)"
);
assert_eq!(
encoded[0], 0xFB,
"first byte of 251-length varint must be 0xFB marker"
);
let (decoded, _): (String, _) =
decode_from_slice(&encoded).expect("decode 251-byte string failed");
assert_eq!(decoded, s);
}
#[test]
fn test_string_emoji_roundtrip() {
let s = "Hello 🦀".to_string();
let encoded = encode_to_vec(&s).expect("encode emoji string failed");
let (decoded, _): (String, _) =
decode_from_slice(&encoded).expect("decode emoji string failed");
assert_eq!(decoded, s);
}
#[test]
fn test_string_null_bytes_roundtrip() {
let s = "foo\0bar".to_string();
let encoded = encode_to_vec(&s).expect("encode null-bytes string failed");
let (decoded, _): (String, _) =
decode_from_slice(&encoded).expect("decode null-bytes string failed");
assert_eq!(decoded, s);
assert_eq!(decoded.len(), 7, "null byte must be counted in the length");
}
#[test]
fn test_string_all_printable_ascii_roundtrip() {
let s: String = (0x20u8..=0x7E).map(|b| b as char).collect();
assert_eq!(s.len(), 95, "must have 95 printable ASCII chars");
let encoded = encode_to_vec(&s).expect("encode printable ASCII string failed");
let (decoded, _): (String, _) =
decode_from_slice(&encoded).expect("decode printable ASCII string failed");
assert_eq!(decoded, s);
}
#[test]
fn test_string_cjk_multibyte_roundtrip() {
let s = "日本語テスト".to_string();
let encoded = encode_to_vec(&s).expect("encode CJK string failed");
let (decoded, _): (String, _) = decode_from_slice(&encoded).expect("decode CJK string failed");
assert_eq!(decoded, s);
}
#[test]
fn test_vec_of_strings_roundtrip() {
let v: Vec<String> = vec![String::new(), "short".to_string(), "x".repeat(300)];
let encoded = encode_to_vec(&v).expect("encode Vec<String> failed");
let (decoded, _): (Vec<String>, _) =
decode_from_slice(&encoded).expect("decode Vec<String> failed");
assert_eq!(decoded, v);
}
#[test]
fn test_option_string_roundtrip() {
let some_val: Option<String> = Some("option content".to_string());
let enc_some = encode_to_vec(&some_val).expect("encode Some(String) failed");
let (dec_some, _): (Option<String>, _) =
decode_from_slice(&enc_some).expect("decode Some(String) failed");
assert_eq!(dec_some, some_val);
let none_val: Option<String> = None;
let enc_none = encode_to_vec(&none_val).expect("encode None failed");
let (dec_none, _): (Option<String>, _) =
decode_from_slice(&enc_none).expect("decode None failed");
assert_eq!(dec_none, none_val);
}
#[allow(clippy::type_complexity)]
#[test]
fn test_nested_vec_of_strings_roundtrip() {
let v: Vec<Vec<String>> = vec![
vec!["alpha".to_string(), "beta".to_string()],
vec![],
vec!["γ".to_string(), "δ".to_string(), "🦀".to_string()],
];
let encoded = encode_to_vec(&v).expect("encode Vec<Vec<String>> failed");
let (decoded, _): (Vec<Vec<String>>, _) =
decode_from_slice(&encoded).expect("decode Vec<Vec<String>> failed");
assert_eq!(decoded, v);
}
#[test]
fn test_string_whitespace_control_chars_roundtrip() {
let s = "line1\nline2\r\ntabbed\there".to_string();
let encoded = encode_to_vec(&s).expect("encode control-char string failed");
let (decoded, _): (String, _) =
decode_from_slice(&encoded).expect("decode control-char string failed");
assert_eq!(decoded, s);
}
#[test]
fn test_string_10000_chars_roundtrip() {
let s = "abcdefghij".repeat(1_000); assert_eq!(s.len(), 10_000);
let encoded = encode_to_vec(&s).expect("encode 10000-char string failed");
let (decoded, _): (String, _) =
decode_from_slice(&encoded).expect("decode 10000-char string failed");
assert_eq!(decoded, s);
}
#[test]
fn test_string_empty_byte_size() {
let s = String::new();
let encoded = encode_to_vec(&s).expect("encode empty String failed");
assert_eq!(encoded.len(), 1);
assert_eq!(encoded[0], 0x00);
let (decoded, _): (String, _) =
decode_from_slice(&encoded).expect("decode empty String failed");
assert_eq!(decoded, "");
}
#[test]
fn test_string_hello_byte_size() {
let s = "hello".to_string();
let encoded = encode_to_vec(&s).expect("encode 'hello' failed");
assert_eq!(encoded.len(), 6, "'hello' must encode to 6 bytes");
assert_eq!(encoded[0], 5, "length prefix must be 5");
assert_eq!(&encoded[1..], b"hello", "content bytes must match");
let (decoded, _): (String, _) = decode_from_slice(&encoded).expect("decode 'hello' failed");
assert_eq!(decoded, s);
}
#[test]
fn test_string_big_endian_config_roundtrip() {
let s = "big endian test 🌏".to_string();
let cfg = config::standard().with_big_endian();
let encoded = encode_to_vec_with_config(&s, cfg).expect("encode big-endian string failed");
let (decoded, _): (String, _) =
decode_from_slice_with_config(&encoded, cfg).expect("decode big-endian string failed");
assert_eq!(decoded, s);
}
#[test]
fn test_string_fixed_int_config_roundtrip() {
let s = "fixed int encoding test".to_string();
let cfg = config::standard().with_fixed_int_encoding();
let encoded = encode_to_vec_with_config(&s, cfg).expect("encode fixed-int string failed");
let (decoded, _): (String, _) =
decode_from_slice_with_config(&encoded, cfg).expect("decode fixed-int string failed");
assert_eq!(decoded, s);
}
#[test]
fn test_string_decode_tight_limit_fails() {
let s = "z".repeat(100);
let unlimited_bytes =
encode_to_vec_with_config(&s, config::standard()).expect("unlimited encode failed");
let small_cfg = config::standard().with_limit::<4>();
let result: Result<(String, _), _> = decode_from_slice_with_config(&unlimited_bytes, small_cfg);
assert!(
result.is_err(),
"decoding a 100-byte string with a 4-byte limit must fail"
);
}
#[allow(clippy::type_complexity)]
#[test]
fn test_string_triple_tuple_roundtrip() {
let t = (
"first".to_string(),
"second".to_string(),
"third".to_string(),
);
let encoded = encode_to_vec(&t).expect("encode (String, String, String) failed");
let (decoded, _): ((String, String, String), _) =
decode_from_slice(&encoded).expect("decode (String, String, String) failed");
assert_eq!(decoded, t);
}
#[test]
fn test_btreemap_string_string_roundtrip() {
let mut map = BTreeMap::new();
map.insert("key_alpha".to_string(), "value_one".to_string());
map.insert("key_beta".to_string(), "value_two".to_string());
map.insert("key_gamma".to_string(), "value_three".to_string());
map.insert(String::new(), "empty key".to_string());
let encoded = encode_to_vec(&map).expect("encode BTreeMap<String, String> failed");
let (decoded, _): (BTreeMap<String, String>, _) =
decode_from_slice(&encoded).expect("decode BTreeMap<String, String> failed");
assert_eq!(decoded, map);
}
#[test]
fn test_string_only_whitespace_roundtrip() {
let s = " \t\t\n\n\r\n ".to_string();
let encoded = encode_to_vec(&s).expect("encode whitespace-only string failed");
let (decoded, _): (String, _) =
decode_from_slice(&encoded).expect("decode whitespace-only string failed");
assert_eq!(decoded, s);
}
#[test]
fn test_string_four_byte_utf8_roundtrip() {
let s = "𝕳𝖊𝖑𝖑𝖔".to_string();
assert_eq!(s.len(), 20, "each Fraktur char is 4 UTF-8 bytes");
let encoded = encode_to_vec(&s).expect("encode 4-byte UTF-8 string failed");
let (decoded, _): (String, _) =
decode_from_slice(&encoded).expect("decode 4-byte UTF-8 string failed");
assert_eq!(decoded, s);
assert_eq!(decoded.chars().count(), 5, "must preserve 5 codepoints");
}