pub use encoding_scheme::*;
pub use encoding_serialization::{deserialize_scheme, serialize_scheme};
pub use errors::{EncodingSerializationError, SchemeValidationError};
mod encoding_serialization {
use super::EncodingSerializationError;
use crate::{EncodingScheme, EncodingSchemeForm};
pub fn serialize_scheme(scheme: &EncodingScheme) -> Result<Vec<u8>, EncodingSerializationError> {
let mut result_vec: Vec<u8> = [].to_vec();
let mut pos = 0_u32;
let mut cur_byte_num = 0;
let mut cur_bit_num = 0_u8;
for form in scheme.iter() {
let (bit_count, prefix_len, prefix) = form.params();
let mut acc = 0_u64;
if prefix_len > 31 {
return Err(EncodingSerializationError::BadEncodingForm);
}
if bit_count < 1 || bit_count > 31 {
return Err(EncodingSerializationError::BadEncodingForm);
}
if prefix_len > 0 {
acc = acc | prefix as u64;
}
acc = acc << 5;
acc = acc | bit_count as u64;
acc = acc << 5;
acc = acc | prefix_len as u64;
let bits_needed = 5 + 5 + prefix_len;
for _ in 0..bits_needed {
if pos % 8 == 0 {
result_vec.push(0);
cur_byte_num = cur_byte_num + 1;
cur_bit_num = 0;
}
let mask = 1 << cur_bit_num;
if (acc % 2) == 1 {
result_vec[cur_byte_num - 1] = result_vec[cur_byte_num - 1] | mask;
}
acc = acc >> 1;
cur_bit_num = cur_bit_num + 1;
pos = pos + 1;
}
assert_eq!(acc, 0);
}
Ok(result_vec)
}
pub fn deserialize_scheme(scheme_bytes: &[u8]) -> Result<EncodingScheme, EncodingSerializationError> {
if scheme_bytes.len() < 2 {
return Err(EncodingSerializationError::BadSerializedData);
}
let mut result = Vec::new();
let mut cur_pos = (scheme_bytes.len() * 8) as u32;
loop {
cur_pos = cur_pos - 5;
let prefix_len = read_bits(scheme_bytes, cur_pos, 5);
cur_pos = cur_pos - 5;
let bit_count = read_bits(scheme_bytes, cur_pos, 5);
cur_pos = cur_pos - prefix_len;
let prefix = read_bits(scheme_bytes, cur_pos, prefix_len as u8);
result.push(EncodingSchemeForm::try_new(bit_count as u8, prefix_len as u8, prefix).expect("invalid encoding scheme form"));
if cur_pos < (5 + 5) {
break;
}
}
let ret_scheme = EncodingScheme::try_new(&result).map_err(|_| EncodingSerializationError::BadSerializedData)?;
Ok(ret_scheme)
}
fn read_bits(data: &[u8], position: u32, bits_amount: u8) -> u32 {
assert!(bits_amount <= 32);
assert!(position + bits_amount as u32 <= (data.len() as u32) * 8);
let mut acc = 0;
if bits_amount == 0 {
return acc;
}
let mut pos = position;
let mut cur_byte_num;
let mut cur_bit_num;
let mut bits_left = bits_amount;
while bits_left > 0 {
cur_byte_num = (pos - (pos % 8)) / 8;
cur_bit_num = pos % 8;
let byte_mask = 128 >> cur_bit_num;
acc = acc << 1;
let cur_byte = data[data.len() - 1 - cur_byte_num as usize];
if (cur_byte & byte_mask) == 0 {
acc = acc & (!1);
} else {
acc = acc | 1;
}
pos = pos + 1;
bits_left = bits_left - 1;
}
acc
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{EncodingScheme, SchemeValidationError};
fn encoding_scheme(forms: &[EncodingSchemeForm]) -> EncodingScheme {
EncodingScheme::try_new(forms).expect("invalid scheme")
}
fn encoding_form(bit_count: u8, prefix_len: u8, prefix: u32) -> EncodingSchemeForm {
EncodingSchemeForm::try_new(bit_count, prefix_len, prefix).expect("invalid form")
}
fn validate(forms: &[EncodingSchemeForm]) -> Result<(), SchemeValidationError> {
EncodingScheme::validate(forms)
}
#[test]
fn test_is_sane_forms() {
let mut input = [encoding_form(4, 1, 1), encoding_form(8, 1, 0)].to_vec();
assert!(validate(&input).is_ok());
input = [encoding_form(4, 1, 1)].to_vec();
assert_eq!(validate(&input), Err(SchemeValidationError::SingleFormWithPrefix));
input = [encoding_form(4, 0, 0), encoding_form(4, 4, 2)].to_vec();
assert_eq!(validate(&input), Err(SchemeValidationError::MultiFormBadPrefix));
input = [
encoding_form(3, 3, 1),
encoding_form(4, 4, 2),
encoding_form(5, 5, 3),
encoding_form(4, 6, 4),
encoding_form(8, 7, 5),
]
.to_vec();
assert_eq!(validate(&input), Err(SchemeValidationError::BitCountNotSorted));
input = [encoding_form(3, 3, 1), encoding_form(31, 29, 5)].to_vec();
assert_eq!(validate(&input), Err(SchemeValidationError::TooBigForm));
input = [encoding_form(3, 3, 1), encoding_form(4, 4, 2), encoding_form(5, 5, 6), encoding_form(8, 9, 2)].to_vec();
assert_eq!(validate(&input), Err(SchemeValidationError::DuplicatePrefix));
}
#[test]
fn test_single_forms() {
let mut input = encoding_scheme([encoding_form(4, 0, 0)].as_ref());
let mut serialized = serialize_scheme(&input).expect("failed to serialize");
assert_eq!(serialized, [0x80, 0x0].to_vec());
let mut deserialized = deserialize_scheme(&serialized).expect("failed to deserialize");
assert_eq!(deserialized, input);
assert!(validate(&deserialized).is_ok());
input = encoding_scheme([encoding_form(8, 0, 0)].as_ref());
serialized = serialize_scheme(&input).expect("failed to serialize");
assert_eq!(serialized, [0x0, 0x1].to_vec());
deserialized = deserialize_scheme(&serialized).expect("failed to deserialize");
assert_eq!(deserialized, input);
assert!(validate(&deserialized).is_ok());
}
#[test]
fn test_multiple_forms() {
let mut input = encoding_scheme([encoding_form(4, 1, 1), encoding_form(8, 1, 0)].as_ref());
let mut serialized = serialize_scheme(&input).expect("failed to serialize");
assert_eq!(serialized, [0x81, 0x0c, 0x08].to_vec());
let mut deserialized = deserialize_scheme(&serialized).expect("failed to deserialize");
assert_eq!(deserialized, input);
assert!(validate(&deserialized).is_ok());
input = encoding_scheme([encoding_form(3, 1, 1), encoding_form(5, 2, 2), encoding_form(8, 2, 0)].as_ref());
serialized = serialize_scheme(&input).expect("failed to serialize");
assert_eq!(serialized, [0x61, 0x14, 0x45, 0x81, 0x0].to_vec());
deserialized = deserialize_scheme(&serialized).expect("failed to deserialize");
assert_eq!(deserialized, input);
assert!(validate(&deserialized).is_ok());
}
#[test]
fn test_forms_pack_with_sequential_parameters() {
let mut pack: Vec<EncodingSchemeForm> = [].to_vec();
let mut prefix = 1_u32;
for i in 1..30 {
let prefix_len = i;
let bit_count = i;
pack.push(encoding_form(bit_count, prefix_len, prefix));
prefix = prefix << 1;
}
assert!(validate(&pack).is_ok());
let scheme = EncodingScheme::try_new(&pack).expect("invalid scheme");
let serialized = serialize_scheme(&scheme).expect("failed to serialize");
let deserialized = deserialize_scheme(&serialized).expect("failed to deserialize");
assert_eq!(deserialized, scheme);
}
}
}
mod encoding_scheme {
use std::collections::HashSet;
use std::ops::Deref;
use crate::encoding::errors::{FormValidationError, SchemeValidationError};
const FORM_MAX_BIT_SIZE: u8 = 59;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EncodingScheme(Vec<EncodingSchemeForm>);
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct EncodingSchemeForm {
bit_count: u8,
prefix_len: u8,
prefix: u32,
}
impl EncodingSchemeForm {
pub fn try_new(bit_count: u8, prefix_len: u8, prefix: u32) -> Result<Self, FormValidationError> {
if bit_count == 0 || bit_count > 31 {
return Err(FormValidationError::BadBitCount);
}
let prefix_max_value = (1 << prefix_len) - 1;
if prefix > prefix_max_value {
return Err(FormValidationError::InvalidPrefixData);
}
Ok(EncodingSchemeForm { bit_count, prefix_len, prefix })
}
pub fn params(&self) -> (u8, u8, u32) {
(self.bit_count, self.prefix_len, self.prefix)
}
pub fn size_bits(&self) -> u8 {
self.bit_count + self.prefix_len
}
}
impl EncodingScheme {
pub fn try_new(forms: &[EncodingSchemeForm]) -> Result<Self, SchemeValidationError> {
let _ = Self::validate(forms)?;
Ok(Self(forms.to_vec()))
}
pub fn validate(forms: &[EncodingSchemeForm]) -> Result<(), SchemeValidationError> {
if forms.len() == 0 || forms.len() > 31 {
return Err(SchemeValidationError::InvalidFormsAmount);
}
if forms.len() == 1 {
let form = forms[0];
let (_, prefix_len, prefix) = form.params();
if prefix_len != 0 || prefix != 0 {
return Err(SchemeValidationError::SingleFormWithPrefix);
}
return Ok(());
}
let mut last_bit_count = 0;
let mut used_prefixes = HashSet::new();
for form in forms {
let (bit_count, prefix_len, prefix) = form.params();
if prefix_len == 0 || prefix_len > 31 {
return Err(SchemeValidationError::MultiFormBadPrefix);
}
if last_bit_count > bit_count {
return Err(SchemeValidationError::BitCountNotSorted);
}
last_bit_count = bit_count;
if form.size_bits() > FORM_MAX_BIT_SIZE {
return Err(SchemeValidationError::TooBigForm);
}
if used_prefixes.contains(&prefix) {
return Err(SchemeValidationError::DuplicatePrefix);
}
used_prefixes.insert(prefix);
}
Ok(())
}
}
impl Deref for EncodingScheme {
type Target = [EncodingSchemeForm];
fn deref(&self) -> &Self::Target {
&self.0
}
}
pub mod schemes {
use super::{EncodingScheme, EncodingSchemeForm};
lazy_static! {
pub static ref F4: EncodingScheme = encoding_scheme(&[EncodingSchemeForm {
bit_count: 4,
prefix_len: 0,
prefix: 0,
}]);
pub static ref F8: EncodingScheme = encoding_scheme(&[EncodingSchemeForm {
bit_count: 8,
prefix_len: 0,
prefix: 0,
}]);
pub static ref V48: EncodingScheme = encoding_scheme(&[
EncodingSchemeForm {
bit_count: 4,
prefix_len: 1,
prefix: 0b01,
},
EncodingSchemeForm {
bit_count: 8,
prefix_len: 1,
prefix: 0b00,
},
]);
pub static ref V358: EncodingScheme = encoding_scheme(&[
EncodingSchemeForm {
bit_count: 3,
prefix_len: 1,
prefix: 0b01,
},
EncodingSchemeForm {
bit_count: 5,
prefix_len: 2,
prefix: 0b10,
},
EncodingSchemeForm {
bit_count: 8,
prefix_len: 2,
prefix: 0b00,
},
]);
pub static ref V37: EncodingScheme = encoding_scheme(&[
EncodingSchemeForm {
bit_count: 3,
prefix_len: 1,
prefix: 0b01,
},
EncodingSchemeForm {
bit_count: 7,
prefix_len: 1,
prefix: 0b00,
},
]);
}
pub fn all() -> impl Iterator<Item = &'static EncodingScheme> + 'static {
lazy_static! {
static ref ALL: [EncodingScheme; 5] = [F4.clone(), F8.clone(), V48.clone(), V358.clone(), V37.clone()];
}
ALL.iter()
}
fn encoding_scheme(forms: &[EncodingSchemeForm]) -> EncodingScheme {
EncodingScheme::try_new(forms).expect("invalid form")
}
}
#[cfg(test)]
mod tests {
use super::{schemes, EncodingScheme, EncodingSchemeForm};
fn encoding_scheme(forms: &[EncodingSchemeForm]) -> EncodingScheme {
EncodingScheme::try_new(forms).expect("invalid scheme")
}
fn encoding_form(bit_count: u8, prefix_len: u8, prefix: u32) -> EncodingSchemeForm {
EncodingSchemeForm { bit_count, prefix_len, prefix }
}
#[test]
fn encoding_scheme_iteration() {
assert_eq!(
encoding_scheme(&[encoding_form(4, 2, 0b00), encoding_form(4, 2, 0b01)])
.into_iter()
.cloned()
.collect::<Vec<EncodingSchemeForm>>(),
vec![encoding_form(4, 2, 0b00), encoding_form(4, 2, 0b01)]
);
}
#[test]
fn schemes() {
assert_eq!(&**schemes::F8, &[encoding_form(8, 0, 0)]);
assert_eq!(schemes::V358[0].bit_count, 3);
assert_eq!(schemes::V358[2].bit_count, 8);
}
}
}
mod errors {
use thiserror::Error;
#[derive(Error, Debug, PartialEq, Eq)]
pub enum SchemeValidationError {
#[error("Invalid encoding scheme: amount of encoding forms is not in range of (1..32)")]
InvalidFormsAmount,
#[error("Invalid encoding scheme: single form has non-empty prefix")]
SingleFormWithPrefix,
#[error("Invalid encoding scheme: multiple forms - prefix length is out of bounds (1..32)")]
MultiFormBadPrefix,
#[error("Invalid encoding scheme: multiple forms should have bit_count in ascending order")]
BitCountNotSorted,
#[error("Invalid encoding scheme: multiple forms must have unique prefixes")]
DuplicatePrefix,
#[error("Invalid encoding scheme: encoding scheme cannot be represented in the usable space in a 64-bit label")]
TooBigForm,
}
#[derive(Error, Debug, PartialEq, Eq)]
pub enum FormValidationError {
#[error("Invalid encoding form: `bit_count` out of bounds (1..32)")]
BadBitCount,
#[error("Invalid encoding form: `prefix_len` is to little for provided `prefix`")]
InvalidPrefixData,
}
#[derive(Error, Debug, PartialEq, Eq)]
pub enum EncodingSerializationError {
#[error("Invalid serialized encoding scheme")]
BadSerializedData,
#[error("Invalid encoding form")]
BadEncodingForm,
}
}