added some basic validation

This commit is contained in:
Talha Qamar 2024-09-19 14:00:25 +05:00
parent 0e5d5f7de7
commit 923e8b7218
5 changed files with 204 additions and 23 deletions

View file

@ -2,7 +2,7 @@ mod parser;
mod types;
mod protocol;
use crate::idl::parser::parse;
use crate::idl::{parser::parse, types::get_protocols};
use std::io::Read;
use logos::{Lexer, Logos, Skip};
@ -54,8 +54,7 @@ enum Token {
#[token(";", get_token_position)]
SemiColon((usize, usize)),
#[token(",", get_token_position)]
Comma((usize, usize)),
#[token(",", get_token_position)] Comma((usize, usize)),
#[token("=", get_token_position)]
Equal((usize, usize)),
@ -89,7 +88,10 @@ pub fn build_idl(name: String) {
}
}
println!("{:#?}", parse(tokens));
let protocols = get_protocols(parse(tokens));
let data : Vec<u8> = vec![1, 5, 12, 12, 12, 12, 3, 28, 8, 28];
println!("{:#?}", &protocols);
protocols.validate("Foo", "bar" , data).unwrap();
}
fn open_protocol(name: String) -> String {

View file

@ -41,15 +41,15 @@ pub struct EnumMember {
#[derive(Debug, Clone, PartialEq)]
pub struct ProtocolDeclaration{
name : String,
interface : Vec<FuncDeclaration>,
pub name : String,
pub interface : Vec<FuncDeclaration>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct FuncDeclaration {
name : String,
arg_list : Vec<String>,
return_type : String,
pub name : String,
pub arg_list : Vec<String>,
pub return_type : String,
}
macro_rules! consume {

View file

@ -1,14 +1,167 @@
pub struct Protocol {
use std::collections::HashMap;
use crate::idl::types::Type;
#[derive(Debug, Clone, PartialEq)]
pub struct Function{
pub arguments : Vec<String>,
}
impl Protocol {
pub fn is_empty(&self) -> bool {
true
#[derive(Debug, Clone, PartialEq)]
pub struct Protocol{
interface : HashMap<String, Function>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Protocols {
protocols : HashMap<String, Protocol>,
symbol_table : HashMap<String, Type>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ValidationError{
IncorrectVersion,
InvalidHeader,
FunctionDoesNotExist,
ProtocolDoesNotExist,
InvalidSize,
InvalidArgument,
NonExistentType(String),
}
impl Protocols {
pub fn new(symbol_table: HashMap<String, Type>) -> Self {
let protocols = HashMap::new();
Self { protocols, symbol_table }
}
pub fn add_protocol(&mut self, name : String, interface : HashMap<String, Function>) {
self.protocols.insert(name, Protocol::new(interface));
}
pub fn validate_data(&self, data: Vec<u8>) -> bool {
if !data.is_empty() && self.is_empty() {
return false;
pub fn validate(&self, protocol_name : &str, function_name : &str, data : Vec<u8>) -> Result<(), ValidationError>{
match self.protocols.get(protocol_name) {
Some(s) => s.validate(function_name, data, &self.symbol_table),
None => Err(ValidationError::ProtocolDoesNotExist),
}
}
}
impl Protocol {
pub fn new(interface: HashMap<String, Function>) -> Self {
Self {interface}
}
fn validate(&self, function_name : &str, data : Vec<u8>, symbols : &HashMap<String, Type>) -> Result<(), ValidationError> {
match self.interface.get(function_name){
Some(s) => s.validate(data, symbols),
None => Err(ValidationError::FunctionDoesNotExist),
}
true
}
}
impl Function {
fn validate(&self, data : Vec<u8>, symbols : &HashMap<String, Type>) -> Result<(), ValidationError> {
let mut types = Vec::new();
for arg in self.arguments.iter() {
let type_value = symbols.get(arg);
if let Some(type_value) = type_value {
types.push(type_value);
}
else{
return Err(ValidationError::NonExistentType(arg.to_string()));
}
}
let mut data = data.iter();
if let Some(ver) = data.next() {
if *ver == 1 {
// We got the correct version number
// Now to parse individual argumebts
let mut types = types.iter().peekable();
loop {
let type_byte = data.next();
if let Some(type_byte) = type_byte {
let type_value = types.next();
if type_value.is_none() {
return Err(ValidationError::InvalidSize);
}
let type_value = type_value.unwrap();
let data_type = match type_byte {
0 => Some(Type::U64),
1 => Some(Type::U32),
2 => Some(Type::U16),
3 => Some(Type::U8),
4 => Some(Type::I64),
5 => Some(Type::I32),
6 => Some(Type::I16),
7 => Some(Type::I8),
8 => Some(Type::Bool),
9 => Some(Type::F32),
10 => Some(Type::F64),
11 => Some(Type::Str),
_ => None,
};
if data_type.is_none() || data_type.as_ref().unwrap() != *type_value {
println!("{:#?}", *type_value);
return Err(ValidationError::InvalidArgument);
}
match data_type.unwrap(){
Type::U64 | Type::I64 | Type::F64 => {
data.next();
data.next();
data.next();
data.next();
data.next();
data.next();
data.next();
data.next();
},
Type::U32 | Type::I32 | Type::F32 => {
data.next();
data.next();
data.next();
data.next();
},
Type::U16 | Type::I16 => {
data.next();
data.next();
},
Type::U8 | Type::I8 | Type::Bool => {
data.next();
},
Type::Str => todo!(),
_ => panic!("Should not be possible"),
}
} else if types.peek().is_none() {
return Ok(());
}
break;
}
}
else {
return Err(ValidationError::IncorrectVersion);
}
} else {
return Err(ValidationError::InvalidHeader);
}
Ok(())
}
}

View file

@ -1,10 +1,11 @@
use std::collections::HashMap;
use crate::idl::protocol::Protocol;
use crate::idl::parser::AST;
use super::protocol::{Function, Protocols};
#[derive(Debug, Clone, PartialEq)]
enum Type {
pub enum Type {
U64,
U32,
U16,
@ -19,6 +20,7 @@ enum Type {
F32,
F64,
Str,
Struct(StructType),
Enum(EnumType),
@ -26,20 +28,34 @@ enum Type {
}
#[derive(Debug, Clone, PartialEq)]
struct StructType {
pub struct StructType {
members : HashMap<String, String>
}
#[derive(Debug, Clone, PartialEq)]
struct EnumType {
pub struct EnumType {
members : HashMap<String, u8>
}
pub fn get_protocols(ast : AST) -> Vec<Protocol> {
let protocols : Vec<Protocol> = Vec::new();
fn add_builtin_types(symbol_table : &mut HashMap<String, Type>) {
symbol_table.insert("u8".to_string(), Type::U8);
symbol_table.insert("u16".to_string(), Type::U16);
symbol_table.insert("u32".to_string(), Type::U32);
symbol_table.insert("u64".to_string(), Type::U64);
symbol_table.insert("i8".to_string(), Type::I8);
symbol_table.insert("i16".to_string(), Type::I16);
symbol_table.insert("i32".to_string(), Type::I32);
symbol_table.insert("i64".to_string(), Type::I64);
symbol_table.insert("bool".to_string(), Type::Bool);
symbol_table.insert("f32".to_string(), Type::F32);
symbol_table.insert("f64".to_string(), Type::F64);
}
pub fn get_protocols(ast : AST) -> Protocols{
let mut symbol_table : HashMap<String, Type> = HashMap::new();
let declarations = ast.0;
add_builtin_types(&mut symbol_table);
// First Pass
// We just populate the symbol table here
for decl in declarations.iter() {
@ -64,9 +80,16 @@ pub fn get_protocols(ast : AST) -> Vec<Protocol> {
super::parser::Declaration::ProtocolDeclaration(_) => {},
}
}
let mut protocols = Protocols::new(symbol_table);
for decl in declarations.iter(){
match decl {
super::parser::Declaration::ProtocolDeclaration(p) => {
let mut funcs : HashMap<String, Function> = HashMap::new();
for i in p.interface.iter(){
funcs.insert(i.name.to_string(), Function{arguments : i.arg_list.clone()});
}
protocols.add_protocol(p.name.to_string(), funcs);
},
_ => {}
}

View file

@ -0,0 +1,3 @@
protocol Foo{
fn bar(i32, u8, bool) -> void;
}