better parser generation

This commit is contained in:
nora 2022-02-12 21:53:09 +01:00
parent c43126af1f
commit 83778ac2c9
10 changed files with 859 additions and 516 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,5 @@
use crate::classes::generated::Class;
use crate::error::{ConException, ProtocolError, TransError};
use std::collections::HashMap;
mod generated;
@ -5,6 +7,7 @@ mod parse_helper;
pub type Table = HashMap<String, FieldValue>;
#[derive(Debug, Clone, PartialEq)]
pub enum FieldValue {
Boolean(bool),
ShortShortInt(i8),
@ -25,3 +28,19 @@ pub enum FieldValue {
FieldTable(Table),
Void,
}
pub use generated::*;
/// Parses the payload of a method frame into the class/method
pub fn parse_method(payload: &[u8]) -> Result<Class, TransError> {
let nom_result = generated::parse::parse_method(payload);
match nom_result {
Ok(([], class)) => Ok(class),
Ok((_, _)) => Err(ProtocolError::ConException(ConException::SyntaxError).into()),
Err(nom::Err::Incomplete(_)) => {
Err(ProtocolError::ConException(ConException::SyntaxError).into())
}
Err(nom::Err::Failure(err) | nom::Err::Error(err)) => Err(err),
}
}

View file

@ -39,6 +39,7 @@ pub fn long(input: &[u8]) -> IResult<Long> {
pub fn longlong(input: &[u8]) -> IResult<Longlong> {
todo!()
}
// todo: doing this using a vec is a bit wasteful, consider not doing that
pub fn bit(input: &[u8], amount: u8) -> IResult<Vec<Bit>> {
todo!()
}

View file

@ -1,5 +1,6 @@
use crate::error::{ProtocolError, TransError};
use crate::frame;
use crate::frame::FrameType;
use anyhow::Context;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpStream;
@ -27,6 +28,10 @@ impl Connection {
loop {
let frame = frame::read_frame(&mut self.stream, 10000).await?;
debug!(?frame, "received frame");
if frame.kind == FrameType::Method {
let class = super::classes::parse_method(&frame.payload)?;
debug!(?class, "was method frame");
}
}
}

View file

@ -14,10 +14,10 @@ mod frame_type {
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Frame {
/// The type of the frame including its parsed metadata.
kind: FrameType,
channel: u16,
pub kind: FrameType,
pub channel: u16,
/// Includes the whole payload, also including the metadata from each type.
payload: Vec<u8>,
pub payload: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
@ -29,23 +29,6 @@ pub enum FrameType {
Heartbeat = 8,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FrameTypeEnum {
/// 1
Method,
/// 2
Header {
class_id: u16,
body_size: u64,
/// Ordered from high to low
property_flags: u16,
},
/// 3
Body,
/// 8
Heartbeat,
}
pub async fn read_frame<R>(r: &mut R, max_frame_size: usize) -> Result<Frame, TransError>
where
R: AsyncReadExt + Unpin,