forked from AbleOS/ableos
added some basic validation
This commit is contained in:
parent
0e5d5f7de7
commit
923e8b7218
|
@ -2,7 +2,7 @@ mod parser;
|
||||||
mod types;
|
mod types;
|
||||||
mod protocol;
|
mod protocol;
|
||||||
|
|
||||||
use crate::idl::parser::parse;
|
use crate::idl::{parser::parse, types::get_protocols};
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
use logos::{Lexer, Logos, Skip};
|
use logos::{Lexer, Logos, Skip};
|
||||||
|
@ -54,8 +54,7 @@ enum Token {
|
||||||
#[token(";", get_token_position)]
|
#[token(";", get_token_position)]
|
||||||
SemiColon((usize, usize)),
|
SemiColon((usize, usize)),
|
||||||
|
|
||||||
#[token(",", get_token_position)]
|
#[token(",", get_token_position)] Comma((usize, usize)),
|
||||||
Comma((usize, usize)),
|
|
||||||
|
|
||||||
#[token("=", get_token_position)]
|
#[token("=", get_token_position)]
|
||||||
Equal((usize, usize)),
|
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 {
|
fn open_protocol(name: String) -> String {
|
||||||
|
|
|
@ -41,15 +41,15 @@ pub struct EnumMember {
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct ProtocolDeclaration{
|
pub struct ProtocolDeclaration{
|
||||||
name : String,
|
pub name : String,
|
||||||
interface : Vec<FuncDeclaration>,
|
pub interface : Vec<FuncDeclaration>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct FuncDeclaration {
|
pub struct FuncDeclaration {
|
||||||
name : String,
|
pub name : String,
|
||||||
arg_list : Vec<String>,
|
pub arg_list : Vec<String>,
|
||||||
return_type : String,
|
pub return_type : String,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! consume {
|
macro_rules! consume {
|
||||||
|
|
|
@ -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 {
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub fn is_empty(&self) -> bool {
|
pub struct Protocol{
|
||||||
true
|
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 {
|
pub fn validate(&self, protocol_name : &str, function_name : &str, data : Vec<u8>) -> Result<(), ValidationError>{
|
||||||
if !data.is_empty() && self.is_empty() {
|
match self.protocols.get(protocol_name) {
|
||||||
return false;
|
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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::idl::protocol::Protocol;
|
|
||||||
use crate::idl::parser::AST;
|
use crate::idl::parser::AST;
|
||||||
|
|
||||||
|
use super::protocol::{Function, Protocols};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
enum Type {
|
pub enum Type {
|
||||||
U64,
|
U64,
|
||||||
U32,
|
U32,
|
||||||
U16,
|
U16,
|
||||||
|
@ -19,6 +20,7 @@ enum Type {
|
||||||
|
|
||||||
F32,
|
F32,
|
||||||
F64,
|
F64,
|
||||||
|
Str,
|
||||||
|
|
||||||
Struct(StructType),
|
Struct(StructType),
|
||||||
Enum(EnumType),
|
Enum(EnumType),
|
||||||
|
@ -26,20 +28,34 @@ enum Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
struct StructType {
|
pub struct StructType {
|
||||||
members : HashMap<String, String>
|
members : HashMap<String, String>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
struct EnumType {
|
pub struct EnumType {
|
||||||
members : HashMap<String, u8>
|
members : HashMap<String, u8>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn get_protocols(ast : AST) -> Vec<Protocol> {
|
fn add_builtin_types(symbol_table : &mut HashMap<String, Type>) {
|
||||||
let protocols : Vec<Protocol> = Vec::new();
|
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 mut symbol_table : HashMap<String, Type> = HashMap::new();
|
||||||
let declarations = ast.0;
|
let declarations = ast.0;
|
||||||
|
add_builtin_types(&mut symbol_table);
|
||||||
// First Pass
|
// First Pass
|
||||||
// We just populate the symbol table here
|
// We just populate the symbol table here
|
||||||
for decl in declarations.iter() {
|
for decl in declarations.iter() {
|
||||||
|
@ -64,9 +80,16 @@ pub fn get_protocols(ast : AST) -> Vec<Protocol> {
|
||||||
super::parser::Declaration::ProtocolDeclaration(_) => {},
|
super::parser::Declaration::ProtocolDeclaration(_) => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut protocols = Protocols::new(symbol_table);
|
||||||
for decl in declarations.iter(){
|
for decl in declarations.iter(){
|
||||||
match decl {
|
match decl {
|
||||||
super::parser::Declaration::ProtocolDeclaration(p) => {
|
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);
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
3
sysdata/idl/test/src/protocol.aldi
Normal file
3
sysdata/idl/test/src/protocol.aldi
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
protocol Foo{
|
||||||
|
fn bar(i32, u8, bool) -> void;
|
||||||
|
}
|
Loading…
Reference in a new issue