use crate::Compiler::AST::{DataType};
pub const MAGIC_NUMBER: u32 = 0x4D444958;
pub const VERSION_MAJOR: u8 = 1;
pub const VERSION_MINOR: u8 = 0;
pub const VERSION_PATCH: u8 = 0;
pub const HEADER_SIZE: usize = 16;
pub const FOOTER_SIZE: usize = 32; pub const OFFSET_ENTRY_SIZE: usize = 12;
bitflags::bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SectionFlags: u8 {
const NONE = 0x00;
const CONFIG = 0x01; const ENUMS = 0x02; const DATA = 0x04; const SECURITY = 0x08; const IMPORTS = 0x10; const RESERVED_6 = 0x40;
const RESERVED_7 = 0x80;
}
}
#[repr(u32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SectionId {
Config = 0x00000001,
Enums = 0x00000002,
Data = 0x00000003,
Security = 0x00000004,
Imports = 0x00000005,
}
impl SectionId {
pub fn name(&self) -> &'static str {
match self {
SectionId::Config => "@CONFIG",
SectionId::Enums => "@ENUMS",
SectionId::Data => "@DATA",
SectionId::Security => "@SECURITY",
SectionId::Imports => "@IMPORTS",
}
}
pub fn from_u32(value: u32) -> Option<Self> {
match value {
0x00000001 => Some(SectionId::Config),
0x00000002 => Some(SectionId::Enums),
0x00000003 => Some(SectionId::Data),
0x00000004 => Some(SectionId::Security),
0x00000005 => Some(SectionId::Imports),
_ => None,
}
}
}
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ValueTypeTag {
Int32 = 0x01,
Int64 = 0x02, Float32 = 0x03,
Float64 = 0x04,
String = 0x05,
Bool = 0x06,
Null = 0x07,
Array = 0x08,
Object = 0x09,
Date = 0x0A,
Timestamp = 0x0B,
Hex = 0x0C,
Tuple = 0x0D,
Blob = 0x0E,
Regex = 0x0F,
Enum = 0x10,
Invalid = 0xFF,
}
impl ValueTypeTag {
pub fn name(&self) -> &'static str {
match self {
ValueTypeTag::Int32 => "int",
ValueTypeTag::Int64 => "long",
ValueTypeTag::Float32 => "float",
ValueTypeTag::Float64 => "double",
ValueTypeTag::String => "string",
ValueTypeTag::Bool => "bool",
ValueTypeTag::Null => "null",
ValueTypeTag::Array => "array",
ValueTypeTag::Object => "object",
ValueTypeTag::Tuple => "tuple",
ValueTypeTag::Date => "date",
ValueTypeTag::Timestamp => "timestamp",
ValueTypeTag::Hex => "hex",
ValueTypeTag::Blob => "blob",
ValueTypeTag::Regex => "regex",
ValueTypeTag::Enum => "enum",
ValueTypeTag::Invalid => "invalid",
}
}
pub fn from_u8(value: u8) -> Option<Self> {
match value {
0x01 => Some(ValueTypeTag::Int32),
0x02 => Some(ValueTypeTag::Int64),
0x03 => Some(ValueTypeTag::Float32),
0x04 => Some(ValueTypeTag::Float64),
0x05 => Some(ValueTypeTag::String),
0x06 => Some(ValueTypeTag::Bool),
0x07 => Some(ValueTypeTag::Null),
0x08 => Some(ValueTypeTag::Array),
0x09 => Some(ValueTypeTag::Object),
0x0A => Some(ValueTypeTag::Date),
0x0B => Some(ValueTypeTag::Timestamp),
0x0C => Some(ValueTypeTag::Hex),
0x0D => Some(ValueTypeTag::Tuple),
0x0E => Some(ValueTypeTag::Blob),
0x0F => Some(ValueTypeTag::Regex),
0x10 => Some(ValueTypeTag::Enum),
0xFF => Some(ValueTypeTag::Invalid),
_ => None,
}
}
pub fn from_data_type(data_type: DataType) -> Self {
match data_type {
DataType::Int => ValueTypeTag::Int32,
DataType::Long => ValueTypeTag::Int64,
DataType::Float => ValueTypeTag::Float32,
DataType::Double => ValueTypeTag::Float64,
DataType::String => ValueTypeTag::String,
DataType::Bool => ValueTypeTag::Bool,
DataType::Array => ValueTypeTag::Array,
DataType::Tuple => ValueTypeTag::Tuple,
DataType::Object => ValueTypeTag::Object,
DataType::Date => ValueTypeTag::Date,
DataType::Timestamp => ValueTypeTag::Timestamp,
DataType::Hex => ValueTypeTag::Hex,
DataType::Blob => ValueTypeTag::Blob,
DataType::Regex => ValueTypeTag::Regex,
DataType::Enum => ValueTypeTag::Enum,
_ => ValueTypeTag::Invalid,
}
}
}
pub const MAX_STRING_LENGTH: usize = 1024 * 1024; pub const MAX_ARRAY_LENGTH: usize = 1024 * 1024; pub const MAX_OBJECT_PROPERTIES: usize = 100_000; pub const MAX_NESTING_DEPTH: usize = 5;
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BlobEncoding {
Base64 = 0x01,
Base32 = 0x02,
Hex = 0x03,
Raw = 0x04,
Auto = 0xFF,
}
impl BlobEncoding {
pub fn detect(data: &str) -> Self {
if data.chars().all(|c| c.is_ascii_hexdigit()) {
return BlobEncoding::Hex;
}
if data.chars().all(|c| matches!(c, 'A'..='Z' | '2'..='7' | '=')) {
return BlobEncoding::Base32;
}
BlobEncoding::Base64
}
pub fn validate(&self, data: &str) -> bool {
match self {
BlobEncoding::Base64 => {
use base64::{Engine as _, engine::general_purpose};
general_purpose::STANDARD.decode(data).is_ok()
}
BlobEncoding::Hex => {
data.len() % 2 == 0 && data.chars().all(|c| c.is_ascii_hexdigit())
}
BlobEncoding::Base32 => {
data.chars().all(|c| matches!(c, 'A'..='Z' | '2'..='7' | '='))
}
BlobEncoding::Raw => true,
BlobEncoding::Auto => false,
}
}
}
pub fn is_valid_magic_number(magic: u32) -> bool {
magic == MAGIC_NUMBER
}
pub fn is_valid_version(major: u8, minor: u8, patch: u8) -> bool {
major == VERSION_MAJOR && minor == VERSION_MINOR && patch == VERSION_PATCH
}