use crate::bitwise::get_mask;
use crate::encode_decode::Base32;
use crate::errors::DecodeLengthError;
use crate::ip::ClientSubnetEncodingData;
const CLIENT_ROUTING_LABEL_VERSION: u16 = 1;
#[derive(Copy, Clone, Debug)]
pub struct DecodedClientRoutingLabel {
pub client_sdk_version: u16,
pub is_ipv6: bool,
pub client_subnet: [u8; 8],
pub subnet_mask: u8,
pub cgid: u64,
}
#[derive(Copy, Clone, Debug)]
pub struct EncodableData {
pub value: u64,
pub num_bits: u8,
}
impl EncodableData {
pub fn get_next_bits_to_encode(&mut self, num_bits_needed: u8) -> u8 {
self.num_bits -= num_bits_needed;
let mask: u128 = (get_mask(num_bits_needed) as u128) << self.num_bits;
let bits_to_encode = (self.value as u128 & mask) >> self.num_bits;
self.value &= get_mask(self.num_bits);
bits_to_encode as u8
}
pub fn has_bits_for_char(self, num_bits_in_char: u8) -> bool {
self.num_bits >= num_bits_in_char
}
pub fn add_bits(&mut self, num_bits_to_add: u8, value_to_add: u8) {
self.num_bits -= num_bits_to_add;
self.value <<= num_bits_to_add;
self.value |= value_to_add as u64;
}
}
#[derive(Copy, Clone, Debug)]
pub struct ClientRoutingLabel {
pub encodable_data: [EncodableData; 5],
pub encoding_system: Base32,
}
impl Default for ClientRoutingLabel {
fn default() -> Self {
let sdk_version = EncodableData {
value: CLIENT_ROUTING_LABEL_VERSION as u64,
num_bits: 10,
};
let is_ipv6: EncodableData = EncodableData {
value: 0,
num_bits: 1,
};
let client_subnet = EncodableData {
value: 0,
num_bits: 64,
};
let subnet_mask = EncodableData {
value: 0,
num_bits: 6,
};
let cgid = EncodableData {
value: 0,
num_bits: 64,
};
Self {
encodable_data: [sdk_version, is_ipv6, client_subnet, subnet_mask, cgid],
encoding_system: Base32 {},
}
}
}
impl ClientRoutingLabel {
pub fn set_data(&mut self, client_subnet_encoding_data: ClientSubnetEncodingData, cgid: u64) {
self.encodable_data[1].value = client_subnet_encoding_data.is_ipv6;
self.encodable_data[2].value = client_subnet_encoding_data.client_subnet;
self.encodable_data[3].value = client_subnet_encoding_data.subnet_mask;
self.encodable_data[4].value = cgid;
}
pub fn encode(&mut self) -> String {
self.encoding_system.encode(&mut self.encodable_data)
}
pub fn decode(
&mut self,
client_routing_label: &[u8],
) -> Result<DecodedClientRoutingLabel, DecodeLengthError> {
let total_num_bits = self.get_total_num_bits();
let decoded_label = self.encoding_system.decode(
&mut self.encodable_data,
client_routing_label,
total_num_bits,
);
match decoded_label {
Ok(_value) => Ok(self.get_decoded_client_routing_label()),
Err(e) => Err(e),
}
}
pub fn get_total_num_bits(&mut self) -> u8 {
self.encodable_data.iter().fold(0, |a, b| a + b.num_bits)
}
fn get_decoded_client_routing_label(&mut self) -> DecodedClientRoutingLabel {
DecodedClientRoutingLabel {
client_sdk_version: self.encodable_data[0].value as u16,
is_ipv6: self.encodable_data[1].value != 0,
client_subnet: self.encodable_data[2].value.to_be_bytes(),
subnet_mask: self.encodable_data[3].value as u8,
cgid: self.encodable_data[4].value,
}
}
}