use n::env::*;
use std;
use std::collections::hash_map::HashMap;
pub type Byte = u8;
pub type Buffer = [Byte; PACKET_BUFFER_SIZE];
pub type Field<'a> = &'a mut [Byte];
pub type ConstField<'a> = &'a [Byte];
pub type PacketHandler = fn(Packet) -> Packet;
pub const ZERO_BUFFER: Buffer = [0u8; PACKET_BUFFER_SIZE];
#[inline(always)]
pub fn move_field(src: ConstField, dst: Field) -> usize {
let moved_bytes = std::cmp::min(src.len(), dst.len());
for index in 0..moved_bytes {
dst[index] = src[index];
}
moved_bytes
}
#[inline(always)]
pub fn compare_field(a: ConstField, b: ConstField) -> std::cmp::Ordering {
let a_len = a.len();
let b_len = b.len();
if a_len == 0 || b_len == 0 {
a_len.cmp(&b_len)
} else {
match a[0].cmp(&b[0]) {
std::cmp::Ordering::Less => std::cmp::Ordering::Less,
std::cmp::Ordering::Greater => std::cmp::Ordering::Greater,
_ => compare_field(&a[1..], &b[1..]),
}
}
}
pub struct PacketContext<'a> {
u64_val: HashMap<usize, u64>,
u32_val: HashMap<usize, u32>,
u16_val: HashMap<usize, u16>,
u8_val: HashMap<usize, u8>,
usize_val: HashMap<usize, usize>,
bool_val: HashMap<usize, bool>,
string_val: HashMap<usize, &'static str>,
field_val: HashMap<usize, Field<'a>>,
alias_map: HashMap<&'static str, usize>,
alias_base: usize,
}
impl<'a> PacketContext<'a> {
#[inline(always)]
pub fn new() -> PacketContext<'a> {
PacketContext {
u64_val: HashMap::new(),
u32_val: HashMap::new(),
u16_val: HashMap::new(),
u8_val: HashMap::new(),
usize_val: HashMap::new(),
bool_val: HashMap::new(),
string_val: HashMap::new(),
field_val: HashMap::new(),
alias_map: HashMap::new(),
alias_base: 0usize,
}
}
}
pub type PacketContextRef<'a> = Box<PacketContext<'a>>;
#[packet]
pub struct Packet<'a> {
content: Field<'a>,
pub context: PacketContextRef<'a>,
}
impl<'a> Packet<'a> {
#[inline(always)]
pub fn new(field: Field<'a>) -> Packet<'a> {
let packet_context_box = Box::new(PacketContext::new());
Packet {
content: field,
context: packet_context_box,
}
}
}
pub trait ContentReadOperation {
fn read_u8(&self, offset: usize) -> u8;
fn read_u16(&self, offset: usize) -> u16;
fn read_u32(&self, offset: usize) -> u32;
fn read_u64(&self, offset: usize) -> u64;
}
pub trait ContentWriteOperation {
fn write_u8(&mut self, offset: usize, val: u8);
fn write_u16(&mut self, offset: usize, val: u16);
fn write_u32(&mut self, offset: usize, val: u32);
fn write_u64(&mut self, offset: usize, val: u64);
}
impl<'a> ContentReadOperation for ConstField<'a> {
#[inline(always)]
fn read_u8(&self, offset: usize) -> u8 {
self[offset]
}
#[inline(always)]
fn read_u16(&self, offset: usize) -> u16 {
let byte1: u16 = self[offset + 0] as u16;
let byte2: u16 = self[offset + 1] as u16;
byte1 << 8 | byte2 << 0
}
#[inline(always)]
fn read_u32(&self, offset: usize) -> u32 {
let byte1: u32 = self[offset + 0] as u32;
let byte2: u32 = self[offset + 1] as u32;
let byte3: u32 = self[offset + 2] as u32;
let byte4: u32 = self[offset + 3] as u32;
byte1 << 24 | byte2 << 16 | byte3 << 8 | byte4 << 0
}
#[inline(always)]
fn read_u64(&self, offset: usize) -> u64 {
let byte1: u64 = self[offset + 0] as u64;
let byte2: u64 = self[offset + 1] as u64;
let byte3: u64 = self[offset + 2] as u64;
let byte4: u64 = self[offset + 3] as u64;
let byte5: u64 = self[offset + 4] as u64;
let byte6: u64 = self[offset + 5] as u64;
let byte7: u64 = self[offset + 6] as u64;
let byte8: u64 = self[offset + 7] as u64;
byte1 << 56 | byte2 << 48 | byte3 << 40 | byte4 << 32 | byte5 << 24 | byte6 << 16 | byte7 << 8 | byte8 << 0
}
}
impl<'a> ContentReadOperation for Field<'a> {
#[inline(always)]
fn read_u8(&self, offset: usize) -> u8 {
self[offset]
}
#[inline(always)]
fn read_u16(&self, offset: usize) -> u16 {
let byte1: u16 = self[offset + 0] as u16;
let byte2: u16 = self[offset + 1] as u16;
byte1 << 8 | byte2 << 0
}
#[inline(always)]
fn read_u32(&self, offset: usize) -> u32 {
let byte1: u32 = self[offset + 0] as u32;
let byte2: u32 = self[offset + 1] as u32;
let byte3: u32 = self[offset + 2] as u32;
let byte4: u32 = self[offset + 3] as u32;
byte1 << 24 | byte2 << 16 | byte3 << 8 | byte4 << 0
}
#[inline(always)]
fn read_u64(&self, offset: usize) -> u64 {
let byte1: u64 = self[offset + 0] as u64;
let byte2: u64 = self[offset + 1] as u64;
let byte3: u64 = self[offset + 2] as u64;
let byte4: u64 = self[offset + 3] as u64;
let byte5: u64 = self[offset + 4] as u64;
let byte6: u64 = self[offset + 5] as u64;
let byte7: u64 = self[offset + 6] as u64;
let byte8: u64 = self[offset + 7] as u64;
byte1 << 56 | byte2 << 48 | byte3 << 40 | byte4 << 32 | byte5 << 24 | byte6 << 16 | byte7 << 8 | byte8 << 0
}
}
impl<'a> ContentWriteOperation for Field<'a> {
#[inline(always)]
fn write_u8(&mut self, offset: usize, val: u8) {
self[offset] = val;
}
#[inline(always)]
fn write_u16(&mut self, offset: usize, val: u16) {
self[offset + 0] = (val >> 8) as u8;
self[offset + 1] = (val & 0xFF) as u8;
}
#[inline(always)]
fn write_u32(&mut self, offset: usize, val: u32) {
self[offset + 0] = (val >> 24 & 0xFF) as u8;
self[offset + 1] = (val >> 16 & 0xFF) as u8;
self[offset + 2] = (val >> 8 & 0xFF) as u8;
self[offset + 3] = (val >> 0 & 0xFF) as u8;
}
#[inline(always)]
fn write_u64(&mut self, offset: usize, val: u64) {
self[offset + 0] = (val >> 56 & 0xFF) as u8;
self[offset + 1] = (val >> 48 & 0xFF) as u8;
self[offset + 2] = (val >> 40 & 0xFF) as u8;
self[offset + 3] = (val >> 32 & 0xFF) as u8;
self[offset + 4] = (val >> 24 & 0xFF) as u8;
self[offset + 5] = (val >> 16 & 0xFF) as u8;
self[offset + 6] = (val >> 8 & 0xFF) as u8;
self[offset + 7] = (val >> 0 & 0xFF) as u8;
}
}
impl<'a> ContentReadOperation for Packet<'a> {
#[inline(always)]
fn read_u8(&self, offset: usize) -> u8 {
self.content.read_u8(offset)
}
#[inline(always)]
fn read_u16(&self, offset: usize) -> u16 {
self.content.read_u16(offset)
}
#[inline(always)]
fn read_u32(&self, offset: usize) -> u32 {
self.content.read_u32(offset)
}
#[inline(always)]
fn read_u64(&self, offset: usize) -> u64 {
self.content.read_u64(offset)
}
}
impl<'a> ContentWriteOperation for Packet<'a> {
#[inline(always)]
fn write_u8(&mut self, offset: usize, val: u8) {
self.content.write_u8(offset, val)
}
#[inline(always)]
fn write_u16(&mut self, offset: usize, val: u16) {
self.content.write_u16(offset, val)
}
#[inline(always)]
fn write_u32(&mut self, offset: usize, val: u32) {
self.content.write_u32(offset, val)
}
#[inline(always)]
fn write_u64(&mut self, offset: usize, val: u64) {
self.content.write_u64(offset, val)
}
}
pub trait OneComplementSum {
fn ones_complement_sum_u16(&self, length: usize) -> u16;
}
pub trait ChecksumAdd {
fn csum_add(&self, prev: u16) -> u16;
}
impl ChecksumAdd for u16 {
#[inline(always)]
fn csum_add(&self, prev: u16) -> u16 {
let mut sum: u32 = prev as u32;
sum = sum + (*self as u32);
((sum >> 16) + (sum & 0xFFFF)) as u16
}
}
impl<'a, T: ContentReadOperation> OneComplementSum for T {
#[inline(always)]
fn ones_complement_sum_u16(&self, length: usize) -> u16 {
let short_count: usize = length / 2;
let remaining = length % 2 != 0;
let mut sum_32 = 0u32;
for x in 0..short_count {
sum_32 = sum_32 + (self.read_u16(x << 1) as u32);
sum_32 = (sum_32 >> 16) + (sum_32 & 0xFFFF);
}
if remaining {
sum_32 = sum_32 + ((self.read_u8(length - 1) as u32) << 8);
sum_32 = (sum_32 >> 16) + (sum_32 & 0xFFFF);
}
assert!(sum_32 <= 0xFFFF);
(sum_32 & 0xFFFF) as u16
}
}
pub trait PacketOperation<'a> {
fn right_packet(self, offset: usize) -> (Packet<'a>, Field<'a>);
fn right_strip(self, offset: usize) -> Packet<'a>;
fn left_packet(self, offset: usize) -> (Packet<'a>, Field<'a>);
fn left_strip(self, offset: usize) -> Packet<'a>;
fn len(&self) -> usize;
}
impl<'a> PacketOperation<'a> for Packet<'a> {
#[inline(always)]
fn right_packet(self, offset: usize) -> (Packet<'a>, Field<'a>) {
match offset {
0 => (self, &mut []),
_ => {
let (left, right) = self.content.split_at_mut(offset);
(Packet {
content: right,
context: self.context,
},
left)
}
}
}
#[inline(always)]
fn right_strip(self, offset: usize) -> Packet<'a> {
match offset {
0 => self,
_ => {
let (_, right) = self.content.split_at_mut(offset);
Packet {
content: right,
context: self.context,
}
}
}
}
#[inline(always)]
fn left_packet(self, offset: usize) -> (Packet<'a>, Field<'a>) {
match offset {
0 => (self, &mut []),
_ => {
let offset = self.content.len() - offset;
let (left, right) = self.content.split_at_mut(offset);
(Packet {
content: left,
context: self.context,
},
right)
}
}
}
#[inline(always)]
fn left_strip(self, offset: usize) -> Packet<'a> {
match offset {
0 => self,
_ => {
let offset = self.content.len() - offset;
let (left, _) = self.content.split_at_mut(offset);
Packet {
content: left,
context: self.context,
}
}
}
}
#[inline(always)]
fn len(&self) -> usize {
self.content.len()
}
}
pub trait PacketConstraint {
fn require_u64(&self, key: &'static str) -> ();
fn require_u32(&self, key: &'static str) -> ();
fn require_u16(&self, key: &'static str) -> ();
fn require_u8(&self, key: &'static str) -> ();
fn require_bool(&self, key: &'static str) -> ();
fn require_string(&self, key: &'static str) -> ();
fn require_field(&self, key: &'static str) -> ();
}
impl<'a> PacketConstraint for Packet<'a> {
#[inline(always)]
fn require_u64(&self, key: &'static str) -> () {
match self.context.alias_map.contains_key(key) {
true => (),
_ => panic!("Context dependency requirement."),
}
}
#[inline(always)]
fn require_u32(&self, key: &'static str) -> () {
match self.context.alias_map.contains_key(key) {
true => (),
_ => panic!("Context dependency requirement."),
}
}
#[inline(always)]
fn require_u16(&self, key: &'static str) -> () {
match self.context.alias_map.contains_key(key) {
true => (),
_ => panic!("Context dependency requirement."),
}
}
#[inline(always)]
fn require_u8(&self, key: &'static str) -> () {
match self.context.alias_map.contains_key(key) {
true => (),
_ => panic!("Context dependency requirement."),
}
}
#[inline(always)]
fn require_bool(&self, key: &'static str) -> () {
match self.context.alias_map.contains_key(key) {
true => (),
_ => panic!("Context dependency requirement."),
}
}
#[inline(always)]
fn require_string(&self, key: &'static str) -> () {
match self.context.alias_map.contains_key(key) {
true => (),
_ => panic!("Context dependency requirement."),
}
}
#[inline(always)]
fn require_field(&self, key: &'static str) -> () {
match self.context.alias_map.contains_key(key) {
true => (),
_ => panic!("Context dependency requirement."),
}
}
}
pub trait ContextReleasedOperation<'a> {
fn get_u64_released(&self, key: &'static str) -> Option<u64>;
fn get_u32_released(&self, key: &'static str) -> Option<u32>;
fn get_u16_released(&self, key: &'static str) -> Option<u16>;
fn get_u8_released(&self, key: &'static str) -> Option<u8>;
fn get_usize_released(&self, key: &'static str) -> Option<usize>;
fn get_bool_released(&self, key: &'static str) -> Option<bool>;
fn get_string_released(&self, key: &'static str) -> Option<&'static str>;
fn get_field_released(&'a self, key: &'static str) -> Option<ConstField<'a>>;
fn take_field_released(&mut self, key: &'static str) -> Option<Field<'a>>;
fn set_u64_released(&mut self, key: &'static str, val: u64) -> Option<u64>;
fn set_u32_released(&mut self, key: &'static str, val: u32) -> Option<u32>;
fn set_u16_released(&mut self, key: &'static str, val: u16) -> Option<u16>;
fn set_u8_released(&mut self, key: &'static str, val: u8) -> Option<u8>;
fn set_usize_released(&mut self, key: &'static str, val: usize) -> Option<usize>;
fn set_bool_released(&mut self, key: &'static str, val: bool) -> Option<bool>;
fn set_string_released(&mut self, key: &'static str, val: &'static str) -> Option<&'static str>;
fn set_field_released(&mut self, key: &'static str, val: Field<'a>) -> Option<Field<'a>>;
}
pub trait ContextOperation<'a> {
fn get_u64(&self, key: &'static str) -> u64;
fn get_u32(&self, key: &'static str) -> u32;
fn get_u16(&self, key: &'static str) -> u16;
fn get_u8(&self, key: &'static str) -> u8;
fn get_usize(&self, key: &'static str) -> usize;
fn get_bool(&self, key: &'static str) -> bool;
fn get_string(&self, key: &'static str) -> &'static str;
fn get_field(&'a self, key: &'static str) -> ConstField<'a>;
fn take_field(&mut self, key: &'static str) -> Field<'a>;
fn set_u64(&mut self, key: &'static str, val: u64) -> ();
fn set_u32(&mut self, key: &'static str, val: u32) -> ();
fn set_u16(&mut self, key: &'static str, val: u16) -> ();
fn set_u8(&mut self, key: &'static str, val: u8) -> ();
fn set_usize(&mut self, key: &'static str, val: usize) -> ();
fn set_bool(&mut self, key: &'static str, val: bool) -> ();
fn set_string(&mut self, key: &'static str, val: &'static str) -> ();
fn set_field(&mut self, key: &'static str, val: Field<'a>) -> ();
}
impl<'a, T: ContextReleasedOperation<'a>> ContextOperation<'a> for T {
#[inline(always)]
fn get_u64(&self, key: &'static str) -> u64 {
self.get_u64_released(key).expect("Must be set")
}
#[inline(always)]
fn get_u32(&self, key: &'static str) -> u32 {
self.get_u32_released(key).expect("Must be set")
}
#[inline(always)]
fn get_u16(&self, key: &'static str) -> u16 {
self.get_u16_released(key).expect("Must be set")
}
#[inline(always)]
fn get_u8(&self, key: &'static str) -> u8 {
self.get_u8_released(key).expect("Must be set")
}
#[inline(always)]
fn get_usize(&self, key: &'static str) -> usize {
self.get_usize_released(key).expect("Must be set")
}
#[inline(always)]
fn get_bool(&self, key: &'static str) -> bool {
self.get_bool_released(key).expect("Must be set")
}
#[inline(always)]
fn get_string(&self, key: &'static str) -> &'static str {
self.get_string_released(key).expect("Must be set")
}
#[inline(always)]
fn get_field(&'a self, key: &'static str) -> ConstField<'a> {
self.get_field_released(key).expect("Must be set")
}
#[inline(always)]
fn take_field(&mut self, key: &'static str) -> Field<'a> {
self.take_field_released(key).expect("Must be set")
}
#[inline(always)]
fn set_u64(&mut self, key: &'static str, val: u64) -> () {
match self.set_u64_released(key, val) {
Some(_) => panic!("Already exist: {}", key),
_ => (),
}
}
#[inline(always)]
fn set_u32(&mut self, key: &'static str, val: u32) -> () {
match self.set_u32_released(key, val) {
Some(_) => panic!("Already exist: {}", key),
_ => (),
}
}
#[inline(always)]
fn set_u16(&mut self, key: &'static str, val: u16) -> () {
match self.set_u16_released(key, val) {
Some(_) => panic!("Already exist: {}", key),
_ => (),
}
}
#[inline(always)]
fn set_u8(&mut self, key: &'static str, val: u8) -> () {
match self.set_u8_released(key, val) {
Some(_) => panic!("Already exist: {}", key),
_ => (),
}
}
#[inline(always)]
fn set_usize(&mut self, key: &'static str, val: usize) -> () {
match self.set_usize_released(key, val) {
Some(_) => panic!("Already exist: {}", key),
_ => (),
}
}
#[inline(always)]
fn set_bool(&mut self, key: &'static str, val: bool) -> () {
match self.set_bool_released(key, val) {
Some(_) => panic!("Already exist: {}", key),
_ => (),
}
}
#[inline(always)]
fn set_string(&mut self, key: &'static str, val: &'static str) -> () {
match self.set_string_released(key, val) {
Some(_) => panic!("Already exist: {}", key),
_ => (),
}
}
#[inline(always)]
fn set_field(&mut self, key: &'static str, val: Field<'a>) -> () {
match self.set_field_released(key, val) {
Some(_) => panic!("Already exist: {}", key),
_ => (),
}
}
}
pub trait Alias {
fn get_alias(&self, key: &'static str) -> Option<usize>;
fn alloc_alias(&mut self, key: &'static str) -> usize;
fn set_alias(&mut self, val1: &'static str, val2: &'static str) -> ();
}
impl<'a> Alias for PacketContext<'a> {
fn set_alias(&mut self, val1: &'static str, val2: &'static str) -> () {
let val1_exist = self.alias_map.contains_key(val1);
let val2_exist = self.alias_map.contains_key(val2);
match (val1_exist, val2_exist) {
(true, true) => {
match self.alias_map.get(val1).expect("Must exist") == self.alias_map.get(val2).expect("Must exist") {
true => {}
false => {
panic!("Merging namespace is not supported yet.");
}
}
}
(true, false) => {
let val;
{
val = *self.alias_map.get(val1).expect("Must exist");
}
self.alias_map.insert(val2, val);
}
(false, true) => {
let val;
{
val = *self.alias_map.get(val2).expect("Must exist");
}
self.alias_map.insert(val1, val);
}
(false, false) => {
let current = self.alias_base;
self.alias_base = self.alias_base + 1;
self.alias_map.insert(val1, current);
self.alias_map.insert(val2, current);
}
}
}
fn alloc_alias(&mut self, key: &'static str) -> usize {
match self.alias_map.contains_key(key) {
true => self.get_alias(key).expect("Must exist"),
false => {
let current = self.alias_base;
self.alias_base = self.alias_base + 1;
self.alias_map.insert(key, current);
current
}
}
}
fn get_alias(&self, key: &'static str) -> Option<usize> {
match self.alias_map.get(key) {
Some(x) => Some(*x),
None => None,
}
}
}
impl<'a> ContextReleasedOperation<'a> for PacketContext<'a> {
#[inline(always)]
fn get_u64_released(&self, key: &'static str) -> Option<u64> {
match self.get_alias(key) {
Some(key) => {
match self.u64_val.get(&key) {
Some(val) => Some(*val),
_ => None,
}
}
_ => None,
}
}
#[inline(always)]
fn get_u32_released(&self, key: &'static str) -> Option<u32> {
match self.get_alias(key) {
Some(key) => {
match self.u32_val.get(&key) {
Some(val) => Some(*val),
_ => None,
}
}
_ => None,
}
}
#[inline(always)]
fn get_u16_released(&self, key: &'static str) -> Option<u16> {
match self.get_alias(key) {
Some(key) => {
match self.u16_val.get(&key) {
Some(val) => Some(*val),
_ => None,
}
}
_ => None,
}
}
#[inline(always)]
fn get_u8_released(&self, key: &'static str) -> Option<u8> {
match self.get_alias(key) {
Some(key) => {
match self.u8_val.get(&key) {
Some(val) => Some(*val),
_ => None,
}
}
_ => None,
}
}
#[inline(always)]
fn get_usize_released(&self, key: &'static str) -> Option<usize> {
match self.get_alias(key) {
Some(key) => {
match self.usize_val.get(&key) {
Some(val) => Some(*val),
_ => None,
}
}
_ => None,
}
}
#[inline(always)]
fn get_bool_released(&self, key: &'static str) -> Option<bool> {
match self.get_alias(key) {
Some(key) => {
match self.bool_val.get(&key) {
Some(val) => Some(*val),
_ => None,
}
}
_ => None,
}
}
#[inline(always)]
fn get_string_released(&self, key: &'static str) -> Option<&'static str> {
match self.get_alias(key) {
Some(key) => {
match self.string_val.get(&key) {
Some(val) => Some(*val),
_ => None,
}
}
_ => None,
}
}
#[inline(always)]
fn get_field_released(&'a self, key: &'static str) -> Option<ConstField<'a>> {
match self.get_alias(key) {
Some(key) => {
match self.field_val.get(&key) {
Some(val) => Some(*val),
_ => None,
}
}
_ => None,
}
}
#[inline(always)]
fn take_field_released(&mut self, key: &'static str) -> Option<Field<'a>> {
match self.get_alias(key) {
Some(key) => self.field_val.remove(&key),
_ => None,
}
}
#[inline(always)]
fn set_u64_released(&mut self, key: &'static str, val: u64) -> Option<u64> {
let key = self.alloc_alias(key);
self.u64_val.insert(key, val)
}
#[inline(always)]
fn set_u32_released(&mut self, key: &'static str, val: u32) -> Option<u32> {
let key = self.alloc_alias(key);
self.u32_val.insert(key, val)
}
#[inline(always)]
fn set_u16_released(&mut self, key: &'static str, val: u16) -> Option<u16> {
let key = self.alloc_alias(key);
self.u16_val.insert(key, val)
}
#[inline(always)]
fn set_u8_released(&mut self, key: &'static str, val: u8) -> Option<u8> {
let key = self.alloc_alias(key);
self.u8_val.insert(key, val)
}
#[inline(always)]
fn set_usize_released(&mut self, key: &'static str, val: usize) -> Option<usize> {
let key = self.alloc_alias(key);
self.usize_val.insert(key, val)
}
#[inline(always)]
fn set_bool_released(&mut self, key: &'static str, val: bool) -> Option<bool> {
let key = self.alloc_alias(key);
self.bool_val.insert(key, val)
}
#[inline(always)]
fn set_string_released(&mut self, key: &'static str, val: &'static str) -> Option<&'static str> {
let key = self.alloc_alias(key);
self.string_val.insert(key, val)
}
#[inline(always)]
fn set_field_released(&mut self, key: &'static str, val: Field<'a>) -> Option<Field<'a>> {
let key = self.alloc_alias(key);
self.field_val.insert(key, val)
}
}
#[millefeuille]
pub fn dummy_move(packet: Packet) -> Packet {
Packet {
content: packet.content,
context: packet.context,
}
}