use crate::codec_prelude::*;
use crate::producer::clone_from_slice;
use core::fmt::Debug;
use std::format;
use std::string::ToString;
pub async fn assert_codec<T, Symbol>(
t1: &T,
t2: &T,
mut c1: TestConsumer<Symbol, (), ()>,
mut c2: TestConsumer<Symbol, (), ()>,
p1: TestProducer<Symbol, (), ()>,
mut p2: TestProducer<Symbol, (), ()>,
) where
T: Encodable<Symbol> + Decodable<Symbol> + Eq + Debug + Clone,
T::ErrorReason: Debug + Eq,
Symbol: Debug + Default + PartialEq + Clone,
{
let res1 = t1.encode(&mut c1).await;
let res2 = t1.encode(&mut c2).await;
let consumed1 = c1.as_slice();
let consumed2 = c2.as_slice();
let common_len = core::cmp::min(consumed1.len(), consumed2.len());
let status = match (res1, res2) {
(Ok(()), Ok(())) => "Neither consumer errored.".to_string(),
(Err(()), Ok(())) => format!(
"First consumer errored after {} symbols, second did not error.",
consumed1.len()
),
(Ok(()), Err(())) => format!(
"First consumer did not error, second consumer errored after {} symbols.",
consumed2.len()
),
(Err(()), Err(())) => format!(
"First consumer errored after {} symbols, second consumer errored after {} symbols.",
consumed1.len(),
consumed2.len()
),
};
assert_eq!(
&consumed1[..common_len],
&consumed2[..common_len],
"The same value produced two different (prefixes of) encodings for two different test consumers.\n\nValue: {t1:#?}\n\n{status}\n\n\nFirst Consumer: {c1:#?}\n\nSecond Consumer: {c2:#?}\n\nFirst Encoding: {consumed1:?}\n\nSecond Encoding: {consumed2:?}",
);
let enc1 = t1.new_vec_storing_encoding().await;
let enc2 = t2.new_vec_storing_encoding().await;
let res1 = T::decode(&mut p1.clone()).await;
if t1 == t2 {
if enc1 != enc2 {
panic!(
"Two equal values produced the nonequal encodings.\n\nFirst Value: {:#?}\n\nSecond Value: {:#?}\n\nFirst encoding: {:?}\n\nSecond encoding: {:?}",
t1,
t2,
enc1,
enc2,
);
}
} else if enc1 == enc2 {
panic!(
"Two nonequal values produced equal encodings.\n\nFirst Value: {:#?}\n\nSecond Value: {:#?}\n\nFirst encoding: {:?}\n\nSecond encoding: {:?}",
t1,
t2,
enc1,
enc2,
);
}
if t1 != t2 && enc2.starts_with(&enc1[..]) {
panic!(
"The encoding of value one is a prefix of the encoding of value two.\n\nFirst Value: {:#?}\n\nSecond Value: {:#?}\n\nFirst encoding: {:?}\n\nSecond encoding: {:?}",
t1,
t2,
enc1,
enc2,
);
}
if p1 == p2 {
let res2 = T::decode(&mut p2).await;
match (&res1, &res2) {
(Ok(t1), Ok(t2)) => {
if t1 != t2 {
panic!(
"Decoded nonequal values from the same sequence of symbols, because exposed item slot sizes and yield patterns of the producers differed.\n\nFirst Value: {:#?}\n\nSecond Value: {:#?}\n\n First TestProducer: {:?}\n\nSecond TestProducer: {:?}",
t1,
t2,
p1,
p2,
);
} else {
}
}
(Err(err1), Err(err2)) => {
if err1 != err2 {
panic!(
"Got nonequal errors from decoding the same sequence of symbols, because exposed item slot sizes and yield patterns of the producers differed.\n\nFirst Error: {:#?}\n\nSecond Error: {:#?}\n\n First TestProducer: {:?}\n\nSecond TestProducer: {:?}",
err1,
err2,
p1,
p2,
);
} else {
}
}
(res1, res2) => panic!(
"Got different results from decoding the same sequence of symbols, because exposed item slot sizes and yield patterns of the producers differed.\n\nFirst Result: {:#?}\n\nSecond Result: {:#?}\n\n First TestProducer: {:?}\n\nSecond TestProducer: {:?}",
res1,
res2,
p1,
p2,
),
};
}
if let Ok(t) = res1 {
let p1b = p1.clone();
let hopefully_minimal_enc = p1b.already_produced();
if hopefully_minimal_enc.len() > 1 {
let mut p3 =
clone_from_slice(&hopefully_minimal_enc[..hopefully_minimal_enc.len() - 1]);
match T::decode(&mut p3).await {
Err(DecodeError::UnexpectedEndOfInput(())) => {
}
res => panic!(
"Removing the final symbol of a valid encoding and trying to decode again did not yield an UnexpectedEndOfInput error!\n\nThe Valid Encoding: {:?}\n\nWhat It Decoded To: {:#?}\n\nThe Result After Decoding From One Less Symbol: {:?}",
hopefully_minimal_enc,
t,
res,
),
}
}
}
match T::decode(&mut clone_from_slice(&enc1[..])).await {
Ok(dec1) => {
if dec1 != *t1 {
panic!(
"Encoding and then decoding a value yielded a value not equal to the original value.\n\nOriginal: {:#?}\n\nDecoded: {:#?}\n\nEncoding: {:?}\n\n",
t1,
dec1,
&enc1[..],
);
}
}
Err(err) => {
panic!(
"Encoding and then decoding a value resulted in failure to decode.\n\nOriginal: {:#?}\n\nEncoding: {:?}\n\nDecoding Error: {:#?}",
t1,
&enc1[..],
err,
);
}
}
}
async fn assert_known_length_stuff_in_isolation<T, Symbol>(t: &T)
where
T: EncodableKnownLength<Symbol> + Decodable<Symbol> + Eq + Debug + Clone,
T::ErrorReason: Debug + Eq,
Symbol: Debug + Default + PartialEq + Clone,
{
let enc = t.new_boxed_slice_storing_encoding().await;
let claimed_len = t.len_of_encoding();
if enc.len() != claimed_len {
panic!(
"len_of_encoding reported an incorrect len.\n\nValue: {:#?}\n\nClaimed Length: {:?}\n\nActual Encoding Length: {:?}\n\nFull Encoding: {:?}",
t,
claimed_len,
enc.len(),
&enc[..],
);
}
}
pub async fn assert_codec_known_length<T, Symbol>(
t1: &T,
t2: &T,
c1: TestConsumer<Symbol, (), ()>,
c2: TestConsumer<Symbol, (), ()>,
p1: TestProducer<Symbol, (), ()>,
p2: TestProducer<Symbol, (), ()>,
) where
T: EncodableKnownLength<Symbol> + Decodable<Symbol> + Eq + Debug + Clone,
T::ErrorReason: Debug + Eq,
Symbol: Debug + Default + PartialEq + Clone,
{
assert_codec(t1, t2, c1, c2, p1, p2).await;
assert_known_length_stuff_in_isolation(t1).await;
}
async fn assert_canonic_stuff_in_isolation<T, Symbol>(
mut p1: TestProducer<Symbol, (), ()>,
mut p2: TestProducer<Symbol, (), ()>,
) where
T: Encodable<Symbol> + DecodableCanonic<Symbol> + Eq + Debug + Clone,
T::ErrorReason: Debug + Eq,
T::ErrorCanonic: Debug + Eq,
Symbol: Debug + Default + PartialEq + Clone,
{
let mut p1b = p1.clone();
let mut p1c = p1.clone();
let mut p1d = p1.clone();
let mut p1e = p1.clone();
let mut p1f = p1.clone();
if let (Ok(t1), Ok(t2)) = (
T::decode_canonic(&mut p1).await,
T::decode_canonic(&mut p2).await,
) {
if p1.already_produced() != p2.already_produced() && t1 == t2 {
panic!(
"Canonically decoding two non-equal sequences of symbols resulted in equal values.\n\nFirst Sequence: {:?}\n\nSecond Sequence: {:?}\n\nFirst Decoded: {:#?}\n\nSecond Decoded: {:#?}",
p1.already_produced(), p2.already_produced(), t1, t2);
}
}
if let Ok(t) = T::decode_canonic(&mut p1b).await {
let reencoding = t.new_vec_storing_encoding().await;
if p1b.already_produced() != &reencoding[..] {
panic!(
"Successfully canonically decoding a sequence of symbols and then reencoding did not yield the original sequence of symbols.\n\nOriginal sequence: {:?}\n\nDecoded: {:#?}\n\nReencoded symbols: {:?}",
p1b.already_produced(),
t,
&reencoding[..],
);
}
}
if let Ok(t_canonic) = T::decode_canonic(&mut p1c).await {
let res = T::decode(&mut p1d).await;
match res {
Ok(t_general) => {
if t_canonic != t_general {
panic!(
"Successful canonic decoding and successful general decoding of the same sequence of symbols did not produce equal values.\n\nThe Encoding: {:?}\n\nCanonically Decoded: {:#?}\n\nGenerally Decoded: {:#?}",
p1c.already_produced(),
t_canonic,
t_general,
);
}
}
Err(err) => {
panic!(
"Canonic decoding succeeded but general decoding failed for the same sequence of code symbols.\n\nThe Encoding: {:?}\n\nCanonically Decoded: {:#?}\n\nGenerally Decoded Error: {:#?}",
p1c.already_produced(),
t_canonic,
err,
);
}
}
}
if let Err(err_regular) = T::decode(&mut p1e).await {
if let Ok(t_decoded_canonic) = T::decode_canonic(&mut p1f).await {
panic!(
"Regular decoding succeeded but canonic decoding failed for the same sequence of code symbols.\n\nThe Encoding: {:?}\n\nCanonically Decoded: {:#?}\n\nRegular Decoding Error: {:#?}",
p1e.already_produced(),
t_decoded_canonic,
err_regular,
);
}
}
}
pub async fn assert_codec_canonic<T, Symbol>(
t1: &T,
t2: &T,
c1: TestConsumer<Symbol, (), ()>,
c2: TestConsumer<Symbol, (), ()>,
p1: TestProducer<Symbol, (), ()>,
p2: TestProducer<Symbol, (), ()>,
) where
T: Encodable<Symbol> + DecodableCanonic<Symbol> + Eq + Debug + Clone,
T::ErrorReason: Debug + Eq,
T::ErrorCanonic: Debug + Eq,
Symbol: Debug + Default + PartialEq + Clone,
{
assert_codec(t1, t2, c1, c2, p1.clone(), p2.clone()).await;
assert_canonic_stuff_in_isolation::<T, Symbol>(p1, p2).await;
}
pub async fn assert_codec_canonic_and_known_len<T, Symbol>(
t1: &T,
t2: &T,
c1: TestConsumer<Symbol, (), ()>,
c2: TestConsumer<Symbol, (), ()>,
p1: TestProducer<Symbol, (), ()>,
p2: TestProducer<Symbol, (), ()>,
) where
T: EncodableKnownLength<Symbol> + DecodableCanonic<Symbol> + Eq + Debug + Clone,
T::ErrorReason: Debug + Eq,
T::ErrorCanonic: Debug + Eq,
Symbol: Debug + Default + PartialEq + Clone,
{
assert_codec(t1, t2, c1, c2, p1.clone(), p2.clone()).await;
assert_known_length_stuff_in_isolation(t1).await;
assert_canonic_stuff_in_isolation::<T, Symbol>(p1, p2).await;
}