use crate::qrcode::{
cpp_port::Type,
decoder::{ErrorCorrectionLevel, FormatInformation},
};
const MASKED_TEST_FORMAT_INFO: u32 = 0x2BED;
const MASKED_TEST_FORMAT_INFO2: u32 =
((0x2BED << 1) & 0b1111111000000000) | 0b100000000 | (0x2BED & 0b11111111); const UNMASKED_TEST_FORMAT_INFO: u32 = MASKED_TEST_FORMAT_INFO ^ 0x5412;
const MICRO_MASKED_TEST_FORMAT_INFO: u32 = 0x3BBA;
const RMQR_MASKED_TEST_FORMAT_INFO: u32 = 0x20137;
const RMQR_MASKED_TEST_FORMAT_INFO_SUB: u32 = 0x1F1FE;
const FORMAT_INFO_MASK_RMQR: u32 = 0x1FAB2; const FORMAT_INFO_MASK_RMQR_SUB: u32 = 0x20A7B;
fn DoFormatInformationTest(formatInfo: u32, expectedMask: u8, expectedECL: ErrorCorrectionLevel) {
let parsedFormat = FormatInformation::DecodeMQR(formatInfo);
assert!(parsedFormat.isValid());
assert_eq!(expectedMask, parsedFormat.data_mask);
assert_eq!(expectedECL, parsedFormat.error_correction_level);
}
fn RMQRUnsetBits(formatInfoBits: u32, numBits: u32) -> u32 {
let mut formatInfoBits = formatInfoBits;
let mut numBits = numBits as i32;
for i in 0..18 {
if (formatInfoBits & (1 << i)) != 0 {
formatInfoBits ^= 1 << i;
numBits -= 1;
}
if numBits == 0 {
break;
}
}
formatInfoBits
}
fn cpp_eq(rhs: &FormatInformation, lhs: &FormatInformation) {
assert!(rhs.cpp_eq(lhs))
}
#[test]
fn Decode() {
let expected = FormatInformation::DecodeQR(MASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO2);
assert!(expected.isValid());
assert_eq!(0x07, expected.data_mask);
assert_eq!(ErrorCorrectionLevel::Q, expected.error_correction_level);
cpp_eq(
&expected,
&FormatInformation::DecodeQR(UNMASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO2),
)
}
#[test]
fn DecodeWithBitDifference() {
let expected = FormatInformation::DecodeQR(MASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO2);
cpp_eq(
&expected,
&FormatInformation::DecodeQR(
MASKED_TEST_FORMAT_INFO ^ 0x01,
MASKED_TEST_FORMAT_INFO2 ^ 0x01,
),
);
cpp_eq(
&expected,
&FormatInformation::DecodeQR(
MASKED_TEST_FORMAT_INFO ^ 0x03,
MASKED_TEST_FORMAT_INFO2 ^ 0x03,
),
);
cpp_eq(
&expected,
&FormatInformation::DecodeQR(
MASKED_TEST_FORMAT_INFO ^ 0x07,
MASKED_TEST_FORMAT_INFO2 ^ 0x07,
),
);
let unexpected = FormatInformation::DecodeQR(
MASKED_TEST_FORMAT_INFO ^ 0x0F,
MASKED_TEST_FORMAT_INFO2 ^ 0x0F,
);
assert!(!&expected.cpp_eq(&unexpected));
assert!(!(unexpected.isValid() && unexpected.qr_type() == Type::Model2));
}
#[test]
fn DecodeWithMisread() {
let expected = FormatInformation::DecodeQR(MASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO2);
cpp_eq(
&expected,
&FormatInformation::DecodeQR(
MASKED_TEST_FORMAT_INFO ^ 0x03,
MASKED_TEST_FORMAT_INFO2 ^ 0x0F,
),
);
}
#[test]
fn DecodeMicro() {
DoFormatInformationTest(0x4445, 0x0, ErrorCorrectionLevel::L);
DoFormatInformationTest(0x4172, 0x1, ErrorCorrectionLevel::L);
DoFormatInformationTest(0x5fc0, 0x2, ErrorCorrectionLevel::L);
DoFormatInformationTest(0x5af7, 0x3, ErrorCorrectionLevel::L);
DoFormatInformationTest(0x6793, 0x0, ErrorCorrectionLevel::M);
DoFormatInformationTest(0x62a4, 0x1, ErrorCorrectionLevel::M);
DoFormatInformationTest(0x3e8d, 0x2, ErrorCorrectionLevel::Q);
DoFormatInformationTest(MICRO_MASKED_TEST_FORMAT_INFO, 0x3, ErrorCorrectionLevel::Q);
}
#[test]
fn DecodeMicroWithBitDifference() {
let expected = FormatInformation::DecodeMQR(MICRO_MASKED_TEST_FORMAT_INFO);
cpp_eq(
&expected,
&FormatInformation::DecodeMQR(MICRO_MASKED_TEST_FORMAT_INFO ^ 0x01),
);
cpp_eq(
&expected,
&FormatInformation::DecodeMQR(MICRO_MASKED_TEST_FORMAT_INFO ^ 0x03),
);
cpp_eq(
&expected,
&FormatInformation::DecodeMQR(MICRO_MASKED_TEST_FORMAT_INFO ^ 0x07),
);
}
#[test]
fn DecodeRMQR() {
let expected = FormatInformation::DecodeRMQR(
RMQR_MASKED_TEST_FORMAT_INFO,
RMQR_MASKED_TEST_FORMAT_INFO_SUB,
);
assert!(expected.isValid());
assert_eq!(4, expected.data_mask);
assert_eq!(ErrorCorrectionLevel::H, expected.error_correction_level);
assert_eq!(FORMAT_INFO_MASK_RMQR, expected.mask);
}
#[test]
fn DecodeRMQRWithBitDifference() {
let expected = FormatInformation::DecodeRMQR(
RMQR_MASKED_TEST_FORMAT_INFO,
RMQR_MASKED_TEST_FORMAT_INFO_SUB,
);
assert_eq!(expected.error_correction_level, ErrorCorrectionLevel::H);
cpp_eq(
&expected,
&FormatInformation::DecodeRMQR(
RMQRUnsetBits(RMQR_MASKED_TEST_FORMAT_INFO, 1),
RMQRUnsetBits(RMQR_MASKED_TEST_FORMAT_INFO_SUB, 1),
),
);
cpp_eq(
&expected,
&FormatInformation::DecodeRMQR(
RMQRUnsetBits(RMQR_MASKED_TEST_FORMAT_INFO, 2),
RMQRUnsetBits(RMQR_MASKED_TEST_FORMAT_INFO_SUB, 2),
),
);
cpp_eq(
&expected,
&FormatInformation::DecodeRMQR(
RMQRUnsetBits(RMQR_MASKED_TEST_FORMAT_INFO, 3),
RMQRUnsetBits(RMQR_MASKED_TEST_FORMAT_INFO_SUB, 3),
),
);
cpp_eq(
&expected,
&FormatInformation::DecodeRMQR(
RMQRUnsetBits(RMQR_MASKED_TEST_FORMAT_INFO, 4),
RMQRUnsetBits(RMQR_MASKED_TEST_FORMAT_INFO_SUB, 4),
),
);
let unexpected = FormatInformation::DecodeRMQR(
RMQRUnsetBits(RMQR_MASKED_TEST_FORMAT_INFO, 5),
RMQRUnsetBits(RMQR_MASKED_TEST_FORMAT_INFO_SUB, 5),
);
assert!(!(expected == unexpected));
assert!(!(unexpected.isValid()));
assert!(unexpected.qr_type() == Type::RectMicro); }
#[test]
fn DecodeRMQRWithMisread() {
let expected = FormatInformation::DecodeRMQR(
RMQR_MASKED_TEST_FORMAT_INFO,
RMQR_MASKED_TEST_FORMAT_INFO_SUB,
);
{
let actual = FormatInformation::DecodeRMQR(
RMQRUnsetBits(RMQR_MASKED_TEST_FORMAT_INFO, 2),
RMQRUnsetBits(RMQR_MASKED_TEST_FORMAT_INFO_SUB, 4),
);
cpp_eq(&expected, &actual);
assert_eq!(actual.mask, FORMAT_INFO_MASK_RMQR);
}
{
let actual = FormatInformation::DecodeRMQR(
RMQRUnsetBits(RMQR_MASKED_TEST_FORMAT_INFO, 5),
RMQRUnsetBits(RMQR_MASKED_TEST_FORMAT_INFO_SUB, 4),
);
cpp_eq(&expected, &actual);
assert_eq!(actual.mask, FORMAT_INFO_MASK_RMQR_SUB);
}
}