#![cfg(all(feature = "v1", feature = "v2"))]
#![allow(clippy::enum_variant_names)]
use expect_test::expect;
#[cfg(test)]
macro_rules! assert_bits {
($v:expr, $expected:expr) => {
let v = (
($v, $v, $v, $v, $v, $v, $v, $v),
($v, $v, $v, $v, $v, $v, $v, $v),
($v, $v, $v, $v, $v, $v, $v, $v),
($v, $v, $v, $v, $v, $v, $v, $v),
($v, $v, $v, $v, $v, $v, $v, $v),
($v, $v, $v, $v, $v, $v, $v, $v),
($v, $v, $v, $v, $v, $v, $v, $v),
($v, $v, $v, $v, $v, $v, $v, $v),
);
let bytes = compactly::v1::encode(&v);
let decoded = compactly::v1::decode(&bytes);
let ans_bytes = compactly::v2::encode(&v);
let ans_decoded = compactly::v2::decode(&ans_bytes);
let some_v = Some(v);
assert_eq!(decoded, some_v, "decoded value is incorrect");
assert_eq!(ans_decoded, some_v, "ANS decoded value is incorrect");
$expected.assert_eq(&format!(
"v1: {} bits, v2: {} bits",
(bytes.len() + 4) / 8,
(ans_bytes.len() + 4) / 8
));
};
}
#[test]
fn singlet_tuple() {
#[derive(Debug, PartialEq, Eq, compactly::v2::Encode, compactly::v1::Encode)]
pub struct Tuple(usize);
assert_bits!(Tuple(0), expect!["v1: 3 bits, v2: 3 bits"]);
assert_bits!(Tuple(1), expect!["v1: 3 bits, v2: 3 bits"]);
assert_bits!(Tuple(2), expect!["v1: 3 bits, v2: 3 bits"]);
}
#[test]
fn pair_tuple() {
#[derive(Debug, PartialEq, Eq, compactly::v2::Encode, compactly::v1::Encode)]
pub struct Tuple(usize, bool);
assert_bits!(Tuple(0, false), expect!["v1: 4 bits, v2: 4 bits"]);
assert_bits!(Tuple(1, true), expect!["v1: 4 bits, v2: 4 bits"]);
assert_bits!(Tuple(2, false), expect!["v1: 4 bits, v2: 4 bits"]);
assert_bits!(Tuple(2048, false), expect!["v1: 18 bits, v2: 18 bits"]);
}
#[test]
fn zero_size() {
#[derive(Clone, Copy, Debug, PartialEq, Eq, compactly::v2::Encode, compactly::v1::Encode)]
pub struct Tuple;
assert_bits!(Tuple, expect!["v1: 0 bits, v2: 0 bits"]);
assert_bits!([Tuple; 4], expect!["v1: 0 bits, v2: 0 bits"]);
assert_bits!([Tuple; 1024], expect!["v1: 0 bits, v2: 0 bits"]);
}
#[test]
fn derive_strategy_for_newtype() {
use compactly::{v1, v2, Compressible, Mapping, Small, Sorted};
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, v2::Encode, v1::Encode)]
#[compactly(Sorted)]
pub struct NewType(u32);
assert_eq!(v2::encode_with(Sorted, &NewType(0)).len(), 1);
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, v2::Encode, v1::Encode)]
#[compactly(Sorted)]
#[compactly(Small)]
pub struct Both(u32);
assert_eq!(v2::encode_with(Sorted, &Both(0)).len(), 1);
#[derive(Clone, Debug, PartialEq, v2::Encode, v1::Encode)]
#[compactly(Mapping<Small, Compressible>)]
pub struct Map(std::collections::BTreeMap<u32, String>);
let strategy: Mapping<Small, Compressible> = Mapping::default();
assert_eq!(v2::encode_with(strategy, &Map([].into())).len(), 1);
}
#[test]
fn record() {
#[derive(Clone, Copy, Debug, PartialEq, Eq, compactly::v2::Encode, compactly::v1::Encode)]
pub struct Tuple {
size: usize,
happy: bool,
age: usize,
}
assert_bits!(
Tuple {
size: 0,
happy: false,
age: 51
},
expect!["v1: 16 bits, v2: 16 bits"]
);
assert_bits!(
Tuple {
size: 1024,
happy: true,
age: 51
},
expect!["v1: 29 bits, v2: 29 bits"]
);
}
#[test]
fn simple_enum() {
#[derive(Clone, Copy, Debug, PartialEq, Eq, compactly::v2::Encode, compactly::v1::Encode)]
pub enum A {
A,
B,
C,
D,
}
assert_bits!(A::A, expect!["v1: 2 bits, v2: 2 bits"]);
assert_bits!(A::D, expect!["v1: 1 bits, v2: 2 bits"]);
#[derive(Clone, Copy, Debug, PartialEq, Eq, compactly::v2::Encode, compactly::v1::Encode)]
pub enum Bool {
True,
False,
}
assert_bits!(Bool::True, expect!["v1: 1 bits, v2: 1 bits"]);
assert_bits!(Bool::False, expect!["v1: 1 bits, v2: 1 bits"]);
}
#[test]
fn bigger_enum() {
#[derive(Clone, Copy, Debug, PartialEq, Eq, compactly::v2::Encode, compactly::v1::Encode)]
pub enum A {
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
}
assert_bits!(A::A, expect!["v1: 3 bits, v2: 3 bits"]);
assert_bits!(A::D, expect!["v1: 3 bits, v2: 3 bits"]);
assert_bits!(A::J, expect!["v1: 1 bits, v2: 3 bits"]);
}
#[test]
fn weird_enum() {
#[derive(Clone, Copy, Debug, PartialEq, Eq, compactly::v2::Encode, compactly::v1::Encode)]
pub enum A {
A { age: usize },
B { age: bool },
}
assert_bits!(A::A { age: 51 }, expect!["v1: 13 bits, v2: 13 bits"]);
assert_bits!(A::B { age: false }, expect!["v1: 2 bits, v2: 2 bits"]);
}
#[test]
fn fancy_enum() {
#[derive(Clone, Copy, Debug, PartialEq, Eq, compactly::v2::Encode, compactly::v1::Encode)]
pub enum A {
A {
#[compactly(Small)]
age: u64,
},
B {
big: bool,
},
}
assert_bits!(A::A { age: 51 }, expect!["v1: 12 bits, v2: 12 bits"]);
assert_bits!(A::B { big: false }, expect!["v1: 2 bits, v2: 2 bits"]);
#[derive(Clone, Copy, Debug, PartialEq, Eq, compactly::v2::Encode, compactly::v1::Encode)]
pub enum B {
A { age: u64 },
B { big: bool },
}
assert_bits!(B::A { age: 51 }, expect!["v1: 65 bits, v2: 65 bits"]);
assert_bits!(B::B { big: false }, expect!["v1: 2 bits, v2: 2 bits"]);
}
#[test]
fn simplest_generics() {
#[derive(Clone, Copy, Debug, PartialEq, Eq, compactly::v2::Encode, compactly::v1::Encode)]
struct A<T> {
value: T,
}
assert_bits!(A { value: 51_usize }, expect!["v1: 12 bits, v2: 12 bits"]);
}
#[test]
fn low_cardinality() {
#[derive(Clone, Copy, Debug, PartialEq, Eq, compactly::v2::Encode, compactly::v1::Encode)]
struct Data {
#[compactly(LowCardinality)]
value: u64,
}
assert_bits!(Data { value: 51 }, expect!["v1: 65 bits, v2: 65 bits"]);
assert_bits!(
Data { value: u64::MAX },
expect!["v1: 65 bits, v2: 66 bits"]
);
assert_bits!(
(0..1024).map(|value| Data { value }).collect::<Vec<_>>(),
expect!["v1: 8379 bits, v2: 9222 bits"]
);
assert_bits!(
(0..1024)
.map(|v| v % 3)
.map(|value| Data { value })
.collect::<Vec<_>>(),
expect!["v1: 1903 bits, v2: 1902 bits"]
);
}
#[test]
fn unnamed_variants() {
#[derive(compactly::v2::Encode, compactly::v1::Encode)]
enum _SomeEnum {
ValueHolder(String),
OtherValue(u16),
EvenMoreValues(String),
FourthValue(_SubEnum),
}
#[derive(compactly::v2::Encode, compactly::v1::Encode)]
enum _SubEnum {
One,
Two,
}
}
#[test]
fn doc_comments_on_fields() {
#[derive(Clone, Copy, Debug, PartialEq, Eq, compactly::v2::Encode, compactly::v1::Encode)]
struct Documented {
value: u8,
flag: bool,
}
for v in [
Documented {
value: 0,
flag: false,
},
Documented {
value: 42,
flag: true,
},
Documented {
value: 255,
flag: false,
},
] {
let bytes = compactly::v2::encode(&v);
assert_eq!(
compactly::v2::decode(&bytes),
Some(v),
"v2 roundtrip failed"
);
let bytes = compactly::v1::encode(&v);
assert_eq!(
compactly::v1::decode(&bytes),
Some(v),
"v1 roundtrip failed"
);
}
}
#[test]
fn const_generic_array_field() {
#[derive(Clone, Copy, Debug, PartialEq, Eq, compactly::v2::Encode, compactly::v1::Encode)]
struct Buffer<const N: usize> {
data: [u8; N],
}
for v in [
Buffer::<4> { data: [0, 1, 2, 3] },
Buffer::<4> {
data: [255, 0, 128, 7],
},
] {
let bytes = compactly::v2::encode(&v);
assert_eq!(
compactly::v2::decode(&bytes),
Some(v),
"v2 roundtrip failed"
);
let bytes = compactly::v1::encode(&v);
assert_eq!(
compactly::v1::decode(&bytes),
Some(v),
"v1 roundtrip failed"
);
}
}
#[test]
fn field_named_discriminant() {
#[derive(Clone, Copy, Debug, PartialEq, Eq, compactly::v2::Encode, compactly::v1::Encode)]
struct HasDiscriminant {
discriminant: u8,
value: bool,
}
for v in [
HasDiscriminant {
discriminant: 0,
value: false,
},
HasDiscriminant {
discriminant: 42,
value: true,
},
] {
let bytes = compactly::v2::encode(&v);
assert_eq!(
compactly::v2::decode(&bytes),
Some(v),
"v2 roundtrip failed"
);
let bytes = compactly::v1::encode(&v);
assert_eq!(
compactly::v1::decode(&bytes),
Some(v),
"v1 roundtrip failed"
);
}
}
#[test]
fn const_generic_independent() {
#[derive(Clone, Copy, Debug, PartialEq, Eq, compactly::v2::Encode, compactly::v1::Encode)]
struct Tagged<const TAG: usize> {
value: u32,
}
for v in [Tagged::<42> { value: 0 }, Tagged::<42> { value: 100 }] {
let bytes = compactly::v2::encode(&v);
assert_eq!(
compactly::v2::decode(&bytes),
Some(v),
"v2 roundtrip failed"
);
let bytes = compactly::v1::encode(&v);
assert_eq!(
compactly::v1::decode(&bytes),
Some(v),
"v1 roundtrip failed"
);
}
}
#[test]
fn multiple_type_params() {
#[derive(Clone, Copy, Debug, PartialEq, Eq, compactly::v2::Encode, compactly::v1::Encode)]
struct Pair<A, B> {
first: A,
second: B,
}
for v in [
Pair {
first: 3_u8,
second: true,
},
Pair {
first: 0_u8,
second: false,
},
Pair {
first: 255_u8,
second: true,
},
] {
let bytes = compactly::v2::encode(&v);
assert_eq!(
compactly::v2::decode(&bytes),
Some(v),
"v2 roundtrip failed"
);
let bytes = compactly::v1::encode(&v);
assert_eq!(
compactly::v1::decode(&bytes),
Some(v),
"v1 roundtrip failed"
);
}
}
#[test]
fn mixed_enum_variants() {
#[derive(Clone, Copy, Debug, PartialEq, Eq, compactly::v2::Encode, compactly::v1::Encode)]
enum Mixed {
Unit,
Tuple(u8, bool),
Named { x: u8, y: u8 },
}
for v in [
Mixed::Unit,
Mixed::Tuple(0, false),
Mixed::Tuple(42, true),
Mixed::Named { x: 0, y: 0 },
Mixed::Named { x: 1, y: 2 },
] {
let bytes = compactly::v2::encode(&v);
assert_eq!(
compactly::v2::decode(&bytes),
Some(v),
"v2 roundtrip failed"
);
let bytes = compactly::v1::encode(&v);
assert_eq!(
compactly::v1::decode(&bytes),
Some(v),
"v1 roundtrip failed"
);
}
}