mirror of
https://github.com/Noratrieb/haesli.git
synced 2026-01-17 05:05:03 +01:00
better parser generation
This commit is contained in:
parent
c43126af1f
commit
83778ac2c9
10 changed files with 859 additions and 516 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -26,7 +26,6 @@ dependencies = [
|
||||||
name = "amqp_codegen"
|
name = "amqp_codegen"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
|
||||||
"heck",
|
"heck",
|
||||||
"itertools",
|
"itertools",
|
||||||
"strong-xml",
|
"strong-xml",
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.53"
|
|
||||||
heck = "0.4.0"
|
heck = "0.4.0"
|
||||||
itertools = "0.10.3"
|
itertools = "0.10.3"
|
||||||
strong-xml = "0.6.3"
|
strong-xml = "0.6.3"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
|
|
||||||
3
amqp_codegen/README.md
Normal file
3
amqp_codegen/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
codegen for method serialization/deserialization
|
||||||
|
|
||||||
|
run using `cargo r > ../amqp_transport/src/classes/generated.rs`
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
mod parser;
|
mod parser;
|
||||||
|
|
||||||
use crate::parser::codegen_parser;
|
use crate::parser::codegen_parser;
|
||||||
use anyhow::Result;
|
|
||||||
use heck::ToUpperCamelCase;
|
use heck::ToUpperCamelCase;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use strong_xml::XmlRead;
|
use strong_xml::XmlRead;
|
||||||
|
|
@ -76,21 +75,21 @@ struct Field {
|
||||||
asserts: Vec<Assert>,
|
asserts: Vec<Assert>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() {
|
||||||
let content = fs::read_to_string("./amqp-0-9-1.xml").unwrap();
|
let content = fs::read_to_string("./amqp-0-9-1.xml").unwrap();
|
||||||
|
|
||||||
let amqp = Amqp::from_str(&content)?;
|
let amqp = Amqp::from_str(&content).unwrap();
|
||||||
codegen(&amqp)
|
codegen(&amqp);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn codegen(amqp: &Amqp) -> Result<()> {
|
fn codegen(amqp: &Amqp) {
|
||||||
println!("// This file has been generated by `amqp_codegen`. Do not edit it manually.\n");
|
println!("// This file has been generated by `amqp_codegen`. Do not edit it manually.\n");
|
||||||
codegen_domain_defs(amqp)?;
|
codegen_domain_defs(amqp);
|
||||||
codegen_class_defs(amqp)?;
|
codegen_class_defs(amqp);
|
||||||
codegen_parser(amqp)
|
codegen_parser(amqp);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn codegen_domain_defs(amqp: &Amqp) -> Result<()> {
|
fn codegen_domain_defs(amqp: &Amqp) {
|
||||||
for domain in &amqp.domains {
|
for domain in &amqp.domains {
|
||||||
let invariants = invariants(domain.asserts.iter());
|
let invariants = invariants(domain.asserts.iter());
|
||||||
|
|
||||||
|
|
@ -103,11 +102,10 @@ fn codegen_domain_defs(amqp: &Amqp) -> Result<()> {
|
||||||
amqp_type_to_rust_type(&domain.kind),
|
amqp_type_to_rust_type(&domain.kind),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn codegen_class_defs(amqp: &Amqp) -> Result<()> {
|
fn codegen_class_defs(amqp: &Amqp) {
|
||||||
|
println!("#[derive(Debug, Clone, PartialEq)]");
|
||||||
println!("pub enum Class {{");
|
println!("pub enum Class {{");
|
||||||
for class in &amqp.classes {
|
for class in &amqp.classes {
|
||||||
let class_name = class.name.to_upper_camel_case();
|
let class_name = class.name.to_upper_camel_case();
|
||||||
|
|
@ -118,6 +116,7 @@ fn codegen_class_defs(amqp: &Amqp) -> Result<()> {
|
||||||
for class in &amqp.classes {
|
for class in &amqp.classes {
|
||||||
let enum_name = class.name.to_upper_camel_case();
|
let enum_name = class.name.to_upper_camel_case();
|
||||||
println!("/// Index {}, handler = {}", class.index, class.handler);
|
println!("/// Index {}, handler = {}", class.index, class.handler);
|
||||||
|
println!("#[derive(Debug, Clone, PartialEq)]");
|
||||||
println!("pub enum {enum_name} {{");
|
println!("pub enum {enum_name} {{");
|
||||||
for method in &class.methods {
|
for method in &class.methods {
|
||||||
let method_name = method.name.to_upper_camel_case();
|
let method_name = method.name.to_upper_camel_case();
|
||||||
|
|
@ -127,10 +126,8 @@ fn codegen_class_defs(amqp: &Amqp) -> Result<()> {
|
||||||
println!(" {{");
|
println!(" {{");
|
||||||
for field in &method.fields {
|
for field in &method.fields {
|
||||||
let field_name = snake_case(&field.name);
|
let field_name = snake_case(&field.name);
|
||||||
let (field_type, field_docs) = resolve_type(
|
let (field_type, field_docs) =
|
||||||
field.domain.as_ref().or(field.kind.as_ref()).unwrap(),
|
get_invariants_with_type(field_type(field), field.asserts.as_ref());
|
||||||
field.asserts.as_ref(),
|
|
||||||
)?;
|
|
||||||
if !field_docs.is_empty() {
|
if !field_docs.is_empty() {
|
||||||
println!(" /// {field_docs}");
|
println!(" /// {field_docs}");
|
||||||
}
|
}
|
||||||
|
|
@ -143,8 +140,6 @@ fn codegen_class_defs(amqp: &Amqp) -> Result<()> {
|
||||||
}
|
}
|
||||||
println!("}}");
|
println!("}}");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn amqp_type_to_rust_type(amqp_type: &str) -> &'static str {
|
fn amqp_type_to_rust_type(amqp_type: &str) -> &'static str {
|
||||||
|
|
@ -161,13 +156,25 @@ fn amqp_type_to_rust_type(amqp_type: &str) -> &'static str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn field_type(field: &Field) -> &String {
|
||||||
|
field.domain.as_ref().or(field.kind.as_ref()).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_type_from_domain(amqp: &Amqp, domain: &str) -> String {
|
||||||
|
amqp.domains
|
||||||
|
.iter()
|
||||||
|
.find(|d| d.name == domain)
|
||||||
|
.map(|d| d.kind.clone())
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
/// returns (type name, invariant docs)
|
/// returns (type name, invariant docs)
|
||||||
fn resolve_type(domain: &str, asserts: &[Assert]) -> Result<(String, String)> {
|
fn get_invariants_with_type(domain: &str, asserts: &[Assert]) -> (String, String) {
|
||||||
let additional_docs = invariants(asserts.iter());
|
let additional_docs = invariants(asserts.iter());
|
||||||
|
|
||||||
let type_name = domain.to_upper_camel_case();
|
let type_name = domain.to_upper_camel_case();
|
||||||
|
|
||||||
Ok((type_name, additional_docs))
|
(type_name, additional_docs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn snake_case(ident: &str) -> String {
|
fn snake_case(ident: &str) -> String {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::{Amqp, Class, Domain, Method};
|
use crate::{
|
||||||
use anyhow::Result;
|
field_type, resolve_type_from_domain, snake_case, Amqp, Assert, Class, Domain, Method,
|
||||||
|
};
|
||||||
use heck::{ToSnakeCase, ToUpperCamelCase};
|
use heck::{ToSnakeCase, ToUpperCamelCase};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
|
@ -15,7 +16,7 @@ fn domain_function_name(domain_name: &str) -> String {
|
||||||
format!("domain_{domain_name}")
|
format!("domain_{domain_name}")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn codegen_parser(amqp: &Amqp) -> Result<()> {
|
pub(crate) fn codegen_parser(amqp: &Amqp) {
|
||||||
println!(
|
println!(
|
||||||
"pub mod parse {{
|
"pub mod parse {{
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
@ -39,7 +40,7 @@ pub type IResult<'a, T> = nom::IResult<&'a [u8], T, TransError>;
|
||||||
);
|
);
|
||||||
|
|
||||||
for domain in &amqp.domains {
|
for domain in &amqp.domains {
|
||||||
domain_parser(domain)?;
|
domain_parser(domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
for class in &amqp.classes {
|
for class in &amqp.classes {
|
||||||
|
|
@ -56,78 +57,120 @@ pub type IResult<'a, T> = nom::IResult<&'a [u8], T, TransError>;
|
||||||
" let (input, _) = tag([{class_index}])(input)?;
|
" let (input, _) = tag([{class_index}])(input)?;
|
||||||
alt(({all_methods}))(input)"
|
alt(({all_methods}))(input)"
|
||||||
);
|
);
|
||||||
|
});
|
||||||
Ok(())
|
|
||||||
})?;
|
|
||||||
|
|
||||||
for method in &class.methods {
|
for method in &class.methods {
|
||||||
method_parser(class, method)?;
|
method_parser(amqp, class, method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("\n}}");
|
println!("\n}}");
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn domain_parser(domain: &Domain) -> Result<()> {
|
fn domain_parser(domain: &Domain) {
|
||||||
let fn_name = domain_function_name(&domain.name);
|
let fn_name = domain_function_name(&domain.name);
|
||||||
let type_name = domain.kind.to_snake_case();
|
let type_name = domain.kind.to_snake_case();
|
||||||
|
// don't even bother with bit domains, do them manually at call site
|
||||||
|
if type_name != "bit" {
|
||||||
function(&fn_name, &domain.name.to_upper_camel_case(), || {
|
function(&fn_name, &domain.name.to_upper_camel_case(), || {
|
||||||
if domain.asserts.is_empty() {
|
if domain.asserts.is_empty() {
|
||||||
if type_name == "bit" {
|
|
||||||
println!(" todo!() // bit")
|
|
||||||
} else {
|
|
||||||
println!(" {type_name}(input)");
|
println!(" {type_name}(input)");
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
println!(" let (input, result) = {type_name}(input)?;");
|
println!(" let (input, result) = {type_name}(input)?;");
|
||||||
|
|
||||||
for assert in &domain.asserts {
|
for assert in &domain.asserts {
|
||||||
match &*assert.check {
|
assert_check(assert, &type_name, "result");
|
||||||
"notnull" => { /* todo */ }
|
|
||||||
"regexp" => {
|
|
||||||
let value = assert.value.as_ref().unwrap();
|
|
||||||
println!(
|
|
||||||
r#" static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"{value}").unwrap());"#
|
|
||||||
);
|
|
||||||
println!(" if !REGEX.is_match(&result) {{ fail!() }}");
|
|
||||||
}
|
|
||||||
"le" => {} // can't validate this here
|
|
||||||
"length" => {
|
|
||||||
let length = assert.value.as_ref().unwrap();
|
|
||||||
println!(" if result.len() > {length} {{ fail!() }}");
|
|
||||||
}
|
|
||||||
_ => unimplemented!(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
println!(" Ok((input, result))");
|
println!(" Ok((input, result))");
|
||||||
}
|
}
|
||||||
Ok(())
|
});
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn method_parser(class: &Class, method: &Method) -> Result<()> {
|
fn method_parser(amqp: &Amqp, class: &Class, method: &Method) {
|
||||||
let class_name = class.name.to_snake_case();
|
let class_name = class.name.to_snake_case();
|
||||||
|
|
||||||
let function_name = method_function_name(&class_name)(method);
|
let function_name = method_function_name(&class_name)(method);
|
||||||
function(&function_name, "Class", || {
|
function(&function_name, "Class", || {
|
||||||
let method_index = method.index;
|
let method_index = method.index;
|
||||||
println!(" let (input, _) = tag([{method_index}])(input)?;");
|
println!(" let (input, _) = tag([{method_index}])(input)?;");
|
||||||
println!(" todo!()");
|
let mut iter = method.fields.iter().peekable();
|
||||||
for _field in &method.fields {}
|
while let Some(field) = iter.next() {
|
||||||
Ok(())
|
let type_name = resolve_type_from_domain(amqp, field_type(field));
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(())
|
if type_name == "bit" {
|
||||||
|
let mut fields_with_bit = vec![field];
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if iter
|
||||||
|
.peek()
|
||||||
|
.map(|f| resolve_type_from_domain(amqp, field_type(f)) == "bit")
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
|
fields_with_bit.push(iter.next().unwrap());
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn function<F>(name: &str, ret_ty: &str, body: F) -> Result<()>
|
let amount = fields_with_bit.len();
|
||||||
|
println!(" let (input, bits) = bit(input, {amount})?;");
|
||||||
|
|
||||||
|
for (i, field) in fields_with_bit.iter().enumerate() {
|
||||||
|
let field_name = snake_case(&field.name);
|
||||||
|
println!(" let {field_name} = bits[{i}];");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let fn_name = domain_function_name(field_type(field));
|
||||||
|
let field_name = snake_case(&field.name);
|
||||||
|
println!(" let (input, {field_name}) = {fn_name}(input)?;");
|
||||||
|
|
||||||
|
for assert in &field.asserts {
|
||||||
|
assert_check(assert, &type_name, &field_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let class_name = class_name.to_upper_camel_case();
|
||||||
|
let method_name = method.name.to_upper_camel_case();
|
||||||
|
println!(" Ok((input, Class::{class_name}({class_name}::{method_name} {{");
|
||||||
|
for field in &method.fields {
|
||||||
|
let field_name = snake_case(&field.name);
|
||||||
|
println!(" {field_name},");
|
||||||
|
}
|
||||||
|
println!(" }})))");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assert_check(assert: &Assert, type_name: &str, var_name: &str) {
|
||||||
|
match &*assert.check {
|
||||||
|
"notnull" => match type_name {
|
||||||
|
"shortstr" | "longstr" => {
|
||||||
|
println!(" if {var_name}.is_empty() {{ fail!() }}")
|
||||||
|
}
|
||||||
|
"short" => println!(" if {var_name} == 0 {{ fail!() }}"),
|
||||||
|
_ => unimplemented!(),
|
||||||
|
},
|
||||||
|
"regexp" => {
|
||||||
|
let value = assert.value.as_ref().unwrap();
|
||||||
|
println!(
|
||||||
|
r#" static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"{value}").unwrap());"#
|
||||||
|
);
|
||||||
|
println!(" if !REGEX.is_match(&{var_name}) {{ fail!() }}");
|
||||||
|
}
|
||||||
|
"le" => {} // can't validate this here
|
||||||
|
"length" => {
|
||||||
|
let length = assert.value.as_ref().unwrap();
|
||||||
|
println!(" if {var_name}.len() > {length} {{ fail!() }}");
|
||||||
|
}
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn function<F>(name: &str, ret_ty: &str, body: F)
|
||||||
where
|
where
|
||||||
F: FnOnce() -> Result<()>,
|
F: FnOnce(),
|
||||||
{
|
{
|
||||||
println!("fn {name}(input: &[u8]) -> IResult<{ret_ty}> {{");
|
println!("fn {name}(input: &[u8]) -> IResult<{ret_ty}> {{");
|
||||||
body()?;
|
body();
|
||||||
println!("}}");
|
println!("}}");
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
#![allow(unused_variables)]
|
|
||||||
|
|
||||||
// This file has been generated by `amqp_codegen`. Do not edit it manually.
|
// This file has been generated by `amqp_codegen`. Do not edit it manually.
|
||||||
|
|
||||||
pub type ClassId = u16;
|
pub type ClassId = u16;
|
||||||
|
|
@ -55,6 +53,7 @@ pub type Timestamp = u64;
|
||||||
|
|
||||||
pub type Table = super::Table;
|
pub type Table = super::Table;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Class {
|
pub enum Class {
|
||||||
Connection(Connection),
|
Connection(Connection),
|
||||||
Channel(Channel),
|
Channel(Channel),
|
||||||
|
|
@ -65,6 +64,7 @@ pub enum Class {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Index 10, handler = connection
|
/// Index 10, handler = connection
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Connection {
|
pub enum Connection {
|
||||||
/// Index 10
|
/// Index 10
|
||||||
Start {
|
Start {
|
||||||
|
|
@ -87,7 +87,9 @@ pub enum Connection {
|
||||||
locale: Shortstr,
|
locale: Shortstr,
|
||||||
},
|
},
|
||||||
/// Index 20
|
/// Index 20
|
||||||
Secure { challenge: Longstr },
|
Secure {
|
||||||
|
challenge: Longstr,
|
||||||
|
},
|
||||||
/// Index 21
|
/// Index 21
|
||||||
SecureOk {
|
SecureOk {
|
||||||
/// must not be null
|
/// must not be null
|
||||||
|
|
@ -113,7 +115,9 @@ pub enum Connection {
|
||||||
reserved_2: Bit,
|
reserved_2: Bit,
|
||||||
},
|
},
|
||||||
/// Index 41
|
/// Index 41
|
||||||
OpenOk { reserved_1: Shortstr },
|
OpenOk {
|
||||||
|
reserved_1: Shortstr,
|
||||||
|
},
|
||||||
/// Index 50
|
/// Index 50
|
||||||
Close {
|
Close {
|
||||||
reply_code: ReplyCode,
|
reply_code: ReplyCode,
|
||||||
|
|
@ -124,20 +128,31 @@ pub enum Connection {
|
||||||
/// Index 51
|
/// Index 51
|
||||||
CloseOk,
|
CloseOk,
|
||||||
/// Index 60
|
/// Index 60
|
||||||
Blocked { reason: Shortstr },
|
Blocked {
|
||||||
|
reason: Shortstr,
|
||||||
|
},
|
||||||
/// Index 61
|
/// Index 61
|
||||||
Unblocked,
|
Unblocked,
|
||||||
}
|
}
|
||||||
/// Index 20, handler = channel
|
/// Index 20, handler = channel
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Channel {
|
pub enum Channel {
|
||||||
/// Index 10
|
/// Index 10
|
||||||
Open { reserved_1: Shortstr },
|
Open {
|
||||||
|
reserved_1: Shortstr,
|
||||||
|
},
|
||||||
/// Index 11
|
/// Index 11
|
||||||
OpenOk { reserved_1: Longstr },
|
OpenOk {
|
||||||
|
reserved_1: Longstr,
|
||||||
|
},
|
||||||
/// Index 20
|
/// Index 20
|
||||||
Flow { active: Bit },
|
Flow {
|
||||||
|
active: Bit,
|
||||||
|
},
|
||||||
/// Index 21
|
/// Index 21
|
||||||
FlowOk { active: Bit },
|
FlowOk {
|
||||||
|
active: Bit,
|
||||||
|
},
|
||||||
/// Index 40
|
/// Index 40
|
||||||
Close {
|
Close {
|
||||||
reply_code: ReplyCode,
|
reply_code: ReplyCode,
|
||||||
|
|
@ -149,6 +164,7 @@ pub enum Channel {
|
||||||
CloseOk,
|
CloseOk,
|
||||||
}
|
}
|
||||||
/// Index 40, handler = channel
|
/// Index 40, handler = channel
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Exchange {
|
pub enum Exchange {
|
||||||
/// Index 10
|
/// Index 10
|
||||||
Declare {
|
Declare {
|
||||||
|
|
@ -177,6 +193,7 @@ pub enum Exchange {
|
||||||
DeleteOk,
|
DeleteOk,
|
||||||
}
|
}
|
||||||
/// Index 50, handler = channel
|
/// Index 50, handler = channel
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Queue {
|
pub enum Queue {
|
||||||
/// Index 10
|
/// Index 10
|
||||||
Declare {
|
Declare {
|
||||||
|
|
@ -224,7 +241,9 @@ pub enum Queue {
|
||||||
no_wait: NoWait,
|
no_wait: NoWait,
|
||||||
},
|
},
|
||||||
/// Index 31
|
/// Index 31
|
||||||
PurgeOk { message_count: MessageCount },
|
PurgeOk {
|
||||||
|
message_count: MessageCount,
|
||||||
|
},
|
||||||
/// Index 40
|
/// Index 40
|
||||||
Delete {
|
Delete {
|
||||||
reserved_1: Short,
|
reserved_1: Short,
|
||||||
|
|
@ -234,9 +253,12 @@ pub enum Queue {
|
||||||
no_wait: NoWait,
|
no_wait: NoWait,
|
||||||
},
|
},
|
||||||
/// Index 41
|
/// Index 41
|
||||||
DeleteOk { message_count: MessageCount },
|
DeleteOk {
|
||||||
|
message_count: MessageCount,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
/// Index 60, handler = channel
|
/// Index 60, handler = channel
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Basic {
|
pub enum Basic {
|
||||||
/// Index 10
|
/// Index 10
|
||||||
Qos {
|
Qos {
|
||||||
|
|
@ -258,14 +280,18 @@ pub enum Basic {
|
||||||
arguments: Table,
|
arguments: Table,
|
||||||
},
|
},
|
||||||
/// Index 21
|
/// Index 21
|
||||||
ConsumeOk { consumer_tag: ConsumerTag },
|
ConsumeOk {
|
||||||
|
consumer_tag: ConsumerTag,
|
||||||
|
},
|
||||||
/// Index 30
|
/// Index 30
|
||||||
Cancel {
|
Cancel {
|
||||||
consumer_tag: ConsumerTag,
|
consumer_tag: ConsumerTag,
|
||||||
no_wait: NoWait,
|
no_wait: NoWait,
|
||||||
},
|
},
|
||||||
/// Index 31
|
/// Index 31
|
||||||
CancelOk { consumer_tag: ConsumerTag },
|
CancelOk {
|
||||||
|
consumer_tag: ConsumerTag,
|
||||||
|
},
|
||||||
/// Index 40
|
/// Index 40
|
||||||
Publish {
|
Publish {
|
||||||
reserved_1: Short,
|
reserved_1: Short,
|
||||||
|
|
@ -304,7 +330,9 @@ pub enum Basic {
|
||||||
message_count: MessageCount,
|
message_count: MessageCount,
|
||||||
},
|
},
|
||||||
/// Index 72
|
/// Index 72
|
||||||
GetEmpty { reserved_1: Shortstr },
|
GetEmpty {
|
||||||
|
reserved_1: Shortstr,
|
||||||
|
},
|
||||||
/// Index 80
|
/// Index 80
|
||||||
Ack {
|
Ack {
|
||||||
delivery_tag: DeliveryTag,
|
delivery_tag: DeliveryTag,
|
||||||
|
|
@ -316,13 +344,18 @@ pub enum Basic {
|
||||||
requeue: Bit,
|
requeue: Bit,
|
||||||
},
|
},
|
||||||
/// Index 100
|
/// Index 100
|
||||||
RecoverAsync { requeue: Bit },
|
RecoverAsync {
|
||||||
|
requeue: Bit,
|
||||||
|
},
|
||||||
/// Index 110
|
/// Index 110
|
||||||
Recover { requeue: Bit },
|
Recover {
|
||||||
|
requeue: Bit,
|
||||||
|
},
|
||||||
/// Index 111
|
/// Index 111
|
||||||
RecoverOk,
|
RecoverOk,
|
||||||
}
|
}
|
||||||
/// Index 90, handler = channel
|
/// Index 90, handler = channel
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Tx {
|
pub enum Tx {
|
||||||
/// Index 10
|
/// Index 10
|
||||||
Select,
|
Select,
|
||||||
|
|
@ -342,8 +375,8 @@ pub mod parse {
|
||||||
use crate::classes::parse_helper::*;
|
use crate::classes::parse_helper::*;
|
||||||
use crate::error::TransError;
|
use crate::error::TransError;
|
||||||
use nom::{branch::alt, bytes::complete::tag};
|
use nom::{branch::alt, bytes::complete::tag};
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
pub type IResult<'a, T> = nom::IResult<&'a [u8], T, TransError>;
|
pub type IResult<'a, T> = nom::IResult<&'a [u8], T, TransError>;
|
||||||
|
|
||||||
|
|
@ -361,32 +394,18 @@ pub mod parse {
|
||||||
}
|
}
|
||||||
fn domain_exchange_name(input: &[u8]) -> IResult<ExchangeName> {
|
fn domain_exchange_name(input: &[u8]) -> IResult<ExchangeName> {
|
||||||
let (input, result) = shortstr(input)?;
|
let (input, result) = shortstr(input)?;
|
||||||
if result.len() > 127 {
|
if result.len() > 127 { fail!() }
|
||||||
fail!()
|
|
||||||
}
|
|
||||||
static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"^[a-zA-Z0-9-_.:]*$").unwrap());
|
static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"^[a-zA-Z0-9-_.:]*$").unwrap());
|
||||||
if !REGEX.is_match(&result) {
|
if !REGEX.is_match(&result) { fail!() }
|
||||||
fail!()
|
|
||||||
}
|
|
||||||
Ok((input, result))
|
Ok((input, result))
|
||||||
}
|
}
|
||||||
fn domain_method_id(input: &[u8]) -> IResult<MethodId> {
|
fn domain_method_id(input: &[u8]) -> IResult<MethodId> {
|
||||||
short(input)
|
short(input)
|
||||||
}
|
}
|
||||||
fn domain_no_ack(input: &[u8]) -> IResult<NoAck> {
|
|
||||||
todo!() // bit
|
|
||||||
}
|
|
||||||
fn domain_no_local(input: &[u8]) -> IResult<NoLocal> {
|
|
||||||
todo!() // bit
|
|
||||||
}
|
|
||||||
fn domain_no_wait(input: &[u8]) -> IResult<NoWait> {
|
|
||||||
todo!() // bit
|
|
||||||
}
|
|
||||||
fn domain_path(input: &[u8]) -> IResult<Path> {
|
fn domain_path(input: &[u8]) -> IResult<Path> {
|
||||||
let (input, result) = shortstr(input)?;
|
let (input, result) = shortstr(input)?;
|
||||||
if result.len() > 127 {
|
if result.is_empty() { fail!() }
|
||||||
fail!()
|
if result.len() > 127 { fail!() }
|
||||||
}
|
|
||||||
Ok((input, result))
|
Ok((input, result))
|
||||||
}
|
}
|
||||||
fn domain_peer_properties(input: &[u8]) -> IResult<PeerProperties> {
|
fn domain_peer_properties(input: &[u8]) -> IResult<PeerProperties> {
|
||||||
|
|
@ -394,32 +413,24 @@ pub mod parse {
|
||||||
}
|
}
|
||||||
fn domain_queue_name(input: &[u8]) -> IResult<QueueName> {
|
fn domain_queue_name(input: &[u8]) -> IResult<QueueName> {
|
||||||
let (input, result) = shortstr(input)?;
|
let (input, result) = shortstr(input)?;
|
||||||
if result.len() > 127 {
|
if result.len() > 127 { fail!() }
|
||||||
fail!()
|
|
||||||
}
|
|
||||||
static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"^[a-zA-Z0-9-_.:]*$").unwrap());
|
static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"^[a-zA-Z0-9-_.:]*$").unwrap());
|
||||||
if !REGEX.is_match(&result) {
|
if !REGEX.is_match(&result) { fail!() }
|
||||||
fail!()
|
|
||||||
}
|
|
||||||
Ok((input, result))
|
Ok((input, result))
|
||||||
}
|
}
|
||||||
fn domain_redelivered(input: &[u8]) -> IResult<Redelivered> {
|
|
||||||
todo!() // bit
|
|
||||||
}
|
|
||||||
fn domain_message_count(input: &[u8]) -> IResult<MessageCount> {
|
fn domain_message_count(input: &[u8]) -> IResult<MessageCount> {
|
||||||
long(input)
|
long(input)
|
||||||
}
|
}
|
||||||
fn domain_reply_code(input: &[u8]) -> IResult<ReplyCode> {
|
fn domain_reply_code(input: &[u8]) -> IResult<ReplyCode> {
|
||||||
let (input, result) = short(input)?;
|
let (input, result) = short(input)?;
|
||||||
|
if result == 0 { fail!() }
|
||||||
Ok((input, result))
|
Ok((input, result))
|
||||||
}
|
}
|
||||||
fn domain_reply_text(input: &[u8]) -> IResult<ReplyText> {
|
fn domain_reply_text(input: &[u8]) -> IResult<ReplyText> {
|
||||||
let (input, result) = shortstr(input)?;
|
let (input, result) = shortstr(input)?;
|
||||||
|
if result.is_empty() { fail!() }
|
||||||
Ok((input, result))
|
Ok((input, result))
|
||||||
}
|
}
|
||||||
fn domain_bit(input: &[u8]) -> IResult<Bit> {
|
|
||||||
todo!() // bit
|
|
||||||
}
|
|
||||||
fn domain_octet(input: &[u8]) -> IResult<Octet> {
|
fn domain_octet(input: &[u8]) -> IResult<Octet> {
|
||||||
octet(input)
|
octet(input)
|
||||||
}
|
}
|
||||||
|
|
@ -446,307 +457,578 @@ pub mod parse {
|
||||||
}
|
}
|
||||||
fn connection(input: &[u8]) -> IResult<Class> {
|
fn connection(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([10])(input)?;
|
let (input, _) = tag([10])(input)?;
|
||||||
alt((
|
alt((connection_start, connection_start_ok, connection_secure, connection_secure_ok, connection_tune, connection_tune_ok, connection_open, connection_open_ok, connection_close, connection_close_ok, connection_blocked, connection_unblocked))(input)
|
||||||
connection_start,
|
|
||||||
connection_start_ok,
|
|
||||||
connection_secure,
|
|
||||||
connection_secure_ok,
|
|
||||||
connection_tune,
|
|
||||||
connection_tune_ok,
|
|
||||||
connection_open,
|
|
||||||
connection_open_ok,
|
|
||||||
connection_close,
|
|
||||||
connection_close_ok,
|
|
||||||
connection_blocked,
|
|
||||||
connection_unblocked,
|
|
||||||
))(input)
|
|
||||||
}
|
}
|
||||||
fn connection_start(input: &[u8]) -> IResult<Class> {
|
fn connection_start(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([10])(input)?;
|
let (input, _) = tag([10])(input)?;
|
||||||
todo!()
|
let (input, version_major) = domain_octet(input)?;
|
||||||
|
let (input, version_minor) = domain_octet(input)?;
|
||||||
|
let (input, server_properties) = domain_peer_properties(input)?;
|
||||||
|
let (input, mechanisms) = domain_longstr(input)?;
|
||||||
|
if mechanisms.is_empty() { fail!() }
|
||||||
|
let (input, locales) = domain_longstr(input)?;
|
||||||
|
if locales.is_empty() { fail!() }
|
||||||
|
Ok((input, Class::Connection(Connection::Start {
|
||||||
|
version_major,
|
||||||
|
version_minor,
|
||||||
|
server_properties,
|
||||||
|
mechanisms,
|
||||||
|
locales,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn connection_start_ok(input: &[u8]) -> IResult<Class> {
|
fn connection_start_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([11])(input)?;
|
let (input, _) = tag([11])(input)?;
|
||||||
todo!()
|
let (input, client_properties) = domain_peer_properties(input)?;
|
||||||
|
let (input, mechanism) = domain_shortstr(input)?;
|
||||||
|
if mechanism.is_empty() { fail!() }
|
||||||
|
let (input, response) = domain_longstr(input)?;
|
||||||
|
if response.is_empty() { fail!() }
|
||||||
|
let (input, locale) = domain_shortstr(input)?;
|
||||||
|
if locale.is_empty() { fail!() }
|
||||||
|
Ok((input, Class::Connection(Connection::StartOk {
|
||||||
|
client_properties,
|
||||||
|
mechanism,
|
||||||
|
response,
|
||||||
|
locale,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn connection_secure(input: &[u8]) -> IResult<Class> {
|
fn connection_secure(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([20])(input)?;
|
let (input, _) = tag([20])(input)?;
|
||||||
todo!()
|
let (input, challenge) = domain_longstr(input)?;
|
||||||
|
Ok((input, Class::Connection(Connection::Secure {
|
||||||
|
challenge,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn connection_secure_ok(input: &[u8]) -> IResult<Class> {
|
fn connection_secure_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([21])(input)?;
|
let (input, _) = tag([21])(input)?;
|
||||||
todo!()
|
let (input, response) = domain_longstr(input)?;
|
||||||
|
if response.is_empty() { fail!() }
|
||||||
|
Ok((input, Class::Connection(Connection::SecureOk {
|
||||||
|
response,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn connection_tune(input: &[u8]) -> IResult<Class> {
|
fn connection_tune(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([30])(input)?;
|
let (input, _) = tag([30])(input)?;
|
||||||
todo!()
|
let (input, channel_max) = domain_short(input)?;
|
||||||
|
let (input, frame_max) = domain_long(input)?;
|
||||||
|
let (input, heartbeat) = domain_short(input)?;
|
||||||
|
Ok((input, Class::Connection(Connection::Tune {
|
||||||
|
channel_max,
|
||||||
|
frame_max,
|
||||||
|
heartbeat,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn connection_tune_ok(input: &[u8]) -> IResult<Class> {
|
fn connection_tune_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([31])(input)?;
|
let (input, _) = tag([31])(input)?;
|
||||||
todo!()
|
let (input, channel_max) = domain_short(input)?;
|
||||||
|
if channel_max == 0 { fail!() }
|
||||||
|
let (input, frame_max) = domain_long(input)?;
|
||||||
|
let (input, heartbeat) = domain_short(input)?;
|
||||||
|
Ok((input, Class::Connection(Connection::TuneOk {
|
||||||
|
channel_max,
|
||||||
|
frame_max,
|
||||||
|
heartbeat,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn connection_open(input: &[u8]) -> IResult<Class> {
|
fn connection_open(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([40])(input)?;
|
let (input, _) = tag([40])(input)?;
|
||||||
todo!()
|
let (input, virtual_host) = domain_path(input)?;
|
||||||
|
let (input, reserved_1) = domain_shortstr(input)?;
|
||||||
|
let (input, bits) = bit(input, 1)?;
|
||||||
|
let reserved_2 = bits[0];
|
||||||
|
Ok((input, Class::Connection(Connection::Open {
|
||||||
|
virtual_host,
|
||||||
|
reserved_1,
|
||||||
|
reserved_2,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn connection_open_ok(input: &[u8]) -> IResult<Class> {
|
fn connection_open_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([41])(input)?;
|
let (input, _) = tag([41])(input)?;
|
||||||
todo!()
|
let (input, reserved_1) = domain_shortstr(input)?;
|
||||||
|
Ok((input, Class::Connection(Connection::OpenOk {
|
||||||
|
reserved_1,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn connection_close(input: &[u8]) -> IResult<Class> {
|
fn connection_close(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([50])(input)?;
|
let (input, _) = tag([50])(input)?;
|
||||||
todo!()
|
let (input, reply_code) = domain_reply_code(input)?;
|
||||||
|
let (input, reply_text) = domain_reply_text(input)?;
|
||||||
|
let (input, class_id) = domain_class_id(input)?;
|
||||||
|
let (input, method_id) = domain_method_id(input)?;
|
||||||
|
Ok((input, Class::Connection(Connection::Close {
|
||||||
|
reply_code,
|
||||||
|
reply_text,
|
||||||
|
class_id,
|
||||||
|
method_id,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn connection_close_ok(input: &[u8]) -> IResult<Class> {
|
fn connection_close_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([51])(input)?;
|
let (input, _) = tag([51])(input)?;
|
||||||
todo!()
|
Ok((input, Class::Connection(Connection::CloseOk {
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn connection_blocked(input: &[u8]) -> IResult<Class> {
|
fn connection_blocked(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([60])(input)?;
|
let (input, _) = tag([60])(input)?;
|
||||||
todo!()
|
let (input, reason) = domain_shortstr(input)?;
|
||||||
|
Ok((input, Class::Connection(Connection::Blocked {
|
||||||
|
reason,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn connection_unblocked(input: &[u8]) -> IResult<Class> {
|
fn connection_unblocked(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([61])(input)?;
|
let (input, _) = tag([61])(input)?;
|
||||||
todo!()
|
Ok((input, Class::Connection(Connection::Unblocked {
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn channel(input: &[u8]) -> IResult<Class> {
|
fn channel(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([20])(input)?;
|
let (input, _) = tag([20])(input)?;
|
||||||
alt((
|
alt((channel_open, channel_open_ok, channel_flow, channel_flow_ok, channel_close, channel_close_ok))(input)
|
||||||
channel_open,
|
|
||||||
channel_open_ok,
|
|
||||||
channel_flow,
|
|
||||||
channel_flow_ok,
|
|
||||||
channel_close,
|
|
||||||
channel_close_ok,
|
|
||||||
))(input)
|
|
||||||
}
|
}
|
||||||
fn channel_open(input: &[u8]) -> IResult<Class> {
|
fn channel_open(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([10])(input)?;
|
let (input, _) = tag([10])(input)?;
|
||||||
todo!()
|
let (input, reserved_1) = domain_shortstr(input)?;
|
||||||
|
Ok((input, Class::Channel(Channel::Open {
|
||||||
|
reserved_1,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn channel_open_ok(input: &[u8]) -> IResult<Class> {
|
fn channel_open_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([11])(input)?;
|
let (input, _) = tag([11])(input)?;
|
||||||
todo!()
|
let (input, reserved_1) = domain_longstr(input)?;
|
||||||
|
Ok((input, Class::Channel(Channel::OpenOk {
|
||||||
|
reserved_1,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn channel_flow(input: &[u8]) -> IResult<Class> {
|
fn channel_flow(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([20])(input)?;
|
let (input, _) = tag([20])(input)?;
|
||||||
todo!()
|
let (input, bits) = bit(input, 1)?;
|
||||||
|
let active = bits[0];
|
||||||
|
Ok((input, Class::Channel(Channel::Flow {
|
||||||
|
active,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn channel_flow_ok(input: &[u8]) -> IResult<Class> {
|
fn channel_flow_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([21])(input)?;
|
let (input, _) = tag([21])(input)?;
|
||||||
todo!()
|
let (input, bits) = bit(input, 1)?;
|
||||||
|
let active = bits[0];
|
||||||
|
Ok((input, Class::Channel(Channel::FlowOk {
|
||||||
|
active,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn channel_close(input: &[u8]) -> IResult<Class> {
|
fn channel_close(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([40])(input)?;
|
let (input, _) = tag([40])(input)?;
|
||||||
todo!()
|
let (input, reply_code) = domain_reply_code(input)?;
|
||||||
|
let (input, reply_text) = domain_reply_text(input)?;
|
||||||
|
let (input, class_id) = domain_class_id(input)?;
|
||||||
|
let (input, method_id) = domain_method_id(input)?;
|
||||||
|
Ok((input, Class::Channel(Channel::Close {
|
||||||
|
reply_code,
|
||||||
|
reply_text,
|
||||||
|
class_id,
|
||||||
|
method_id,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn channel_close_ok(input: &[u8]) -> IResult<Class> {
|
fn channel_close_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([41])(input)?;
|
let (input, _) = tag([41])(input)?;
|
||||||
todo!()
|
Ok((input, Class::Channel(Channel::CloseOk {
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn exchange(input: &[u8]) -> IResult<Class> {
|
fn exchange(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([40])(input)?;
|
let (input, _) = tag([40])(input)?;
|
||||||
alt((
|
alt((exchange_declare, exchange_declare_ok, exchange_delete, exchange_delete_ok))(input)
|
||||||
exchange_declare,
|
|
||||||
exchange_declare_ok,
|
|
||||||
exchange_delete,
|
|
||||||
exchange_delete_ok,
|
|
||||||
))(input)
|
|
||||||
}
|
}
|
||||||
fn exchange_declare(input: &[u8]) -> IResult<Class> {
|
fn exchange_declare(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([10])(input)?;
|
let (input, _) = tag([10])(input)?;
|
||||||
todo!()
|
let (input, reserved_1) = domain_short(input)?;
|
||||||
|
let (input, exchange) = domain_exchange_name(input)?;
|
||||||
|
if exchange.is_empty() { fail!() }
|
||||||
|
let (input, r#type) = domain_shortstr(input)?;
|
||||||
|
let (input, bits) = bit(input, 5)?;
|
||||||
|
let passive = bits[0];
|
||||||
|
let durable = bits[1];
|
||||||
|
let reserved_2 = bits[2];
|
||||||
|
let reserved_3 = bits[3];
|
||||||
|
let no_wait = bits[4];
|
||||||
|
let (input, arguments) = domain_table(input)?;
|
||||||
|
Ok((input, Class::Exchange(Exchange::Declare {
|
||||||
|
reserved_1,
|
||||||
|
exchange,
|
||||||
|
r#type,
|
||||||
|
passive,
|
||||||
|
durable,
|
||||||
|
reserved_2,
|
||||||
|
reserved_3,
|
||||||
|
no_wait,
|
||||||
|
arguments,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn exchange_declare_ok(input: &[u8]) -> IResult<Class> {
|
fn exchange_declare_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([11])(input)?;
|
let (input, _) = tag([11])(input)?;
|
||||||
todo!()
|
Ok((input, Class::Exchange(Exchange::DeclareOk {
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn exchange_delete(input: &[u8]) -> IResult<Class> {
|
fn exchange_delete(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([20])(input)?;
|
let (input, _) = tag([20])(input)?;
|
||||||
todo!()
|
let (input, reserved_1) = domain_short(input)?;
|
||||||
|
let (input, exchange) = domain_exchange_name(input)?;
|
||||||
|
if exchange.is_empty() { fail!() }
|
||||||
|
let (input, bits) = bit(input, 2)?;
|
||||||
|
let if_unused = bits[0];
|
||||||
|
let no_wait = bits[1];
|
||||||
|
Ok((input, Class::Exchange(Exchange::Delete {
|
||||||
|
reserved_1,
|
||||||
|
exchange,
|
||||||
|
if_unused,
|
||||||
|
no_wait,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn exchange_delete_ok(input: &[u8]) -> IResult<Class> {
|
fn exchange_delete_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([21])(input)?;
|
let (input, _) = tag([21])(input)?;
|
||||||
todo!()
|
Ok((input, Class::Exchange(Exchange::DeleteOk {
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn queue(input: &[u8]) -> IResult<Class> {
|
fn queue(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([50])(input)?;
|
let (input, _) = tag([50])(input)?;
|
||||||
alt((
|
alt((queue_declare, queue_declare_ok, queue_bind, queue_bind_ok, queue_unbind, queue_unbind_ok, queue_purge, queue_purge_ok, queue_delete, queue_delete_ok))(input)
|
||||||
queue_declare,
|
|
||||||
queue_declare_ok,
|
|
||||||
queue_bind,
|
|
||||||
queue_bind_ok,
|
|
||||||
queue_unbind,
|
|
||||||
queue_unbind_ok,
|
|
||||||
queue_purge,
|
|
||||||
queue_purge_ok,
|
|
||||||
queue_delete,
|
|
||||||
queue_delete_ok,
|
|
||||||
))(input)
|
|
||||||
}
|
}
|
||||||
fn queue_declare(input: &[u8]) -> IResult<Class> {
|
fn queue_declare(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([10])(input)?;
|
let (input, _) = tag([10])(input)?;
|
||||||
todo!()
|
let (input, reserved_1) = domain_short(input)?;
|
||||||
|
let (input, queue) = domain_queue_name(input)?;
|
||||||
|
let (input, bits) = bit(input, 5)?;
|
||||||
|
let passive = bits[0];
|
||||||
|
let durable = bits[1];
|
||||||
|
let exclusive = bits[2];
|
||||||
|
let auto_delete = bits[3];
|
||||||
|
let no_wait = bits[4];
|
||||||
|
let (input, arguments) = domain_table(input)?;
|
||||||
|
Ok((input, Class::Queue(Queue::Declare {
|
||||||
|
reserved_1,
|
||||||
|
queue,
|
||||||
|
passive,
|
||||||
|
durable,
|
||||||
|
exclusive,
|
||||||
|
auto_delete,
|
||||||
|
no_wait,
|
||||||
|
arguments,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn queue_declare_ok(input: &[u8]) -> IResult<Class> {
|
fn queue_declare_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([11])(input)?;
|
let (input, _) = tag([11])(input)?;
|
||||||
todo!()
|
let (input, queue) = domain_queue_name(input)?;
|
||||||
|
if queue.is_empty() { fail!() }
|
||||||
|
let (input, message_count) = domain_message_count(input)?;
|
||||||
|
let (input, consumer_count) = domain_long(input)?;
|
||||||
|
Ok((input, Class::Queue(Queue::DeclareOk {
|
||||||
|
queue,
|
||||||
|
message_count,
|
||||||
|
consumer_count,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn queue_bind(input: &[u8]) -> IResult<Class> {
|
fn queue_bind(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([20])(input)?;
|
let (input, _) = tag([20])(input)?;
|
||||||
todo!()
|
let (input, reserved_1) = domain_short(input)?;
|
||||||
|
let (input, queue) = domain_queue_name(input)?;
|
||||||
|
let (input, exchange) = domain_exchange_name(input)?;
|
||||||
|
let (input, routing_key) = domain_shortstr(input)?;
|
||||||
|
let (input, bits) = bit(input, 1)?;
|
||||||
|
let no_wait = bits[0];
|
||||||
|
let (input, arguments) = domain_table(input)?;
|
||||||
|
Ok((input, Class::Queue(Queue::Bind {
|
||||||
|
reserved_1,
|
||||||
|
queue,
|
||||||
|
exchange,
|
||||||
|
routing_key,
|
||||||
|
no_wait,
|
||||||
|
arguments,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn queue_bind_ok(input: &[u8]) -> IResult<Class> {
|
fn queue_bind_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([21])(input)?;
|
let (input, _) = tag([21])(input)?;
|
||||||
todo!()
|
Ok((input, Class::Queue(Queue::BindOk {
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn queue_unbind(input: &[u8]) -> IResult<Class> {
|
fn queue_unbind(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([50])(input)?;
|
let (input, _) = tag([50])(input)?;
|
||||||
todo!()
|
let (input, reserved_1) = domain_short(input)?;
|
||||||
|
let (input, queue) = domain_queue_name(input)?;
|
||||||
|
let (input, exchange) = domain_exchange_name(input)?;
|
||||||
|
let (input, routing_key) = domain_shortstr(input)?;
|
||||||
|
let (input, arguments) = domain_table(input)?;
|
||||||
|
Ok((input, Class::Queue(Queue::Unbind {
|
||||||
|
reserved_1,
|
||||||
|
queue,
|
||||||
|
exchange,
|
||||||
|
routing_key,
|
||||||
|
arguments,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn queue_unbind_ok(input: &[u8]) -> IResult<Class> {
|
fn queue_unbind_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([51])(input)?;
|
let (input, _) = tag([51])(input)?;
|
||||||
todo!()
|
Ok((input, Class::Queue(Queue::UnbindOk {
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn queue_purge(input: &[u8]) -> IResult<Class> {
|
fn queue_purge(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([30])(input)?;
|
let (input, _) = tag([30])(input)?;
|
||||||
todo!()
|
let (input, reserved_1) = domain_short(input)?;
|
||||||
|
let (input, queue) = domain_queue_name(input)?;
|
||||||
|
let (input, bits) = bit(input, 1)?;
|
||||||
|
let no_wait = bits[0];
|
||||||
|
Ok((input, Class::Queue(Queue::Purge {
|
||||||
|
reserved_1,
|
||||||
|
queue,
|
||||||
|
no_wait,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn queue_purge_ok(input: &[u8]) -> IResult<Class> {
|
fn queue_purge_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([31])(input)?;
|
let (input, _) = tag([31])(input)?;
|
||||||
todo!()
|
let (input, message_count) = domain_message_count(input)?;
|
||||||
|
Ok((input, Class::Queue(Queue::PurgeOk {
|
||||||
|
message_count,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn queue_delete(input: &[u8]) -> IResult<Class> {
|
fn queue_delete(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([40])(input)?;
|
let (input, _) = tag([40])(input)?;
|
||||||
todo!()
|
let (input, reserved_1) = domain_short(input)?;
|
||||||
|
let (input, queue) = domain_queue_name(input)?;
|
||||||
|
let (input, bits) = bit(input, 3)?;
|
||||||
|
let if_unused = bits[0];
|
||||||
|
let if_empty = bits[1];
|
||||||
|
let no_wait = bits[2];
|
||||||
|
Ok((input, Class::Queue(Queue::Delete {
|
||||||
|
reserved_1,
|
||||||
|
queue,
|
||||||
|
if_unused,
|
||||||
|
if_empty,
|
||||||
|
no_wait,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn queue_delete_ok(input: &[u8]) -> IResult<Class> {
|
fn queue_delete_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([41])(input)?;
|
let (input, _) = tag([41])(input)?;
|
||||||
todo!()
|
let (input, message_count) = domain_message_count(input)?;
|
||||||
|
Ok((input, Class::Queue(Queue::DeleteOk {
|
||||||
|
message_count,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn basic(input: &[u8]) -> IResult<Class> {
|
fn basic(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([60])(input)?;
|
let (input, _) = tag([60])(input)?;
|
||||||
alt((
|
alt((basic_qos, basic_qos_ok, basic_consume, basic_consume_ok, basic_cancel, basic_cancel_ok, basic_publish, basic_return, basic_deliver, basic_get, basic_get_ok, basic_get_empty, basic_ack, basic_reject, basic_recover_async, basic_recover, basic_recover_ok))(input)
|
||||||
basic_qos,
|
|
||||||
basic_qos_ok,
|
|
||||||
basic_consume,
|
|
||||||
basic_consume_ok,
|
|
||||||
basic_cancel,
|
|
||||||
basic_cancel_ok,
|
|
||||||
basic_publish,
|
|
||||||
basic_return,
|
|
||||||
basic_deliver,
|
|
||||||
basic_get,
|
|
||||||
basic_get_ok,
|
|
||||||
basic_get_empty,
|
|
||||||
basic_ack,
|
|
||||||
basic_reject,
|
|
||||||
basic_recover_async,
|
|
||||||
basic_recover,
|
|
||||||
basic_recover_ok,
|
|
||||||
))(input)
|
|
||||||
}
|
}
|
||||||
fn basic_qos(input: &[u8]) -> IResult<Class> {
|
fn basic_qos(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([10])(input)?;
|
let (input, _) = tag([10])(input)?;
|
||||||
todo!()
|
let (input, prefetch_size) = domain_long(input)?;
|
||||||
|
let (input, prefetch_count) = domain_short(input)?;
|
||||||
|
let (input, bits) = bit(input, 1)?;
|
||||||
|
let global = bits[0];
|
||||||
|
Ok((input, Class::Basic(Basic::Qos {
|
||||||
|
prefetch_size,
|
||||||
|
prefetch_count,
|
||||||
|
global,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn basic_qos_ok(input: &[u8]) -> IResult<Class> {
|
fn basic_qos_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([11])(input)?;
|
let (input, _) = tag([11])(input)?;
|
||||||
todo!()
|
Ok((input, Class::Basic(Basic::QosOk {
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn basic_consume(input: &[u8]) -> IResult<Class> {
|
fn basic_consume(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([20])(input)?;
|
let (input, _) = tag([20])(input)?;
|
||||||
todo!()
|
let (input, reserved_1) = domain_short(input)?;
|
||||||
|
let (input, queue) = domain_queue_name(input)?;
|
||||||
|
let (input, consumer_tag) = domain_consumer_tag(input)?;
|
||||||
|
let (input, bits) = bit(input, 4)?;
|
||||||
|
let no_local = bits[0];
|
||||||
|
let no_ack = bits[1];
|
||||||
|
let exclusive = bits[2];
|
||||||
|
let no_wait = bits[3];
|
||||||
|
let (input, arguments) = domain_table(input)?;
|
||||||
|
Ok((input, Class::Basic(Basic::Consume {
|
||||||
|
reserved_1,
|
||||||
|
queue,
|
||||||
|
consumer_tag,
|
||||||
|
no_local,
|
||||||
|
no_ack,
|
||||||
|
exclusive,
|
||||||
|
no_wait,
|
||||||
|
arguments,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn basic_consume_ok(input: &[u8]) -> IResult<Class> {
|
fn basic_consume_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([21])(input)?;
|
let (input, _) = tag([21])(input)?;
|
||||||
todo!()
|
let (input, consumer_tag) = domain_consumer_tag(input)?;
|
||||||
|
Ok((input, Class::Basic(Basic::ConsumeOk {
|
||||||
|
consumer_tag,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn basic_cancel(input: &[u8]) -> IResult<Class> {
|
fn basic_cancel(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([30])(input)?;
|
let (input, _) = tag([30])(input)?;
|
||||||
todo!()
|
let (input, consumer_tag) = domain_consumer_tag(input)?;
|
||||||
|
let (input, bits) = bit(input, 1)?;
|
||||||
|
let no_wait = bits[0];
|
||||||
|
Ok((input, Class::Basic(Basic::Cancel {
|
||||||
|
consumer_tag,
|
||||||
|
no_wait,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn basic_cancel_ok(input: &[u8]) -> IResult<Class> {
|
fn basic_cancel_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([31])(input)?;
|
let (input, _) = tag([31])(input)?;
|
||||||
todo!()
|
let (input, consumer_tag) = domain_consumer_tag(input)?;
|
||||||
|
Ok((input, Class::Basic(Basic::CancelOk {
|
||||||
|
consumer_tag,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn basic_publish(input: &[u8]) -> IResult<Class> {
|
fn basic_publish(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([40])(input)?;
|
let (input, _) = tag([40])(input)?;
|
||||||
todo!()
|
let (input, reserved_1) = domain_short(input)?;
|
||||||
|
let (input, exchange) = domain_exchange_name(input)?;
|
||||||
|
let (input, routing_key) = domain_shortstr(input)?;
|
||||||
|
let (input, bits) = bit(input, 2)?;
|
||||||
|
let mandatory = bits[0];
|
||||||
|
let immediate = bits[1];
|
||||||
|
Ok((input, Class::Basic(Basic::Publish {
|
||||||
|
reserved_1,
|
||||||
|
exchange,
|
||||||
|
routing_key,
|
||||||
|
mandatory,
|
||||||
|
immediate,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn basic_return(input: &[u8]) -> IResult<Class> {
|
fn basic_return(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([50])(input)?;
|
let (input, _) = tag([50])(input)?;
|
||||||
todo!()
|
let (input, reply_code) = domain_reply_code(input)?;
|
||||||
|
let (input, reply_text) = domain_reply_text(input)?;
|
||||||
|
let (input, exchange) = domain_exchange_name(input)?;
|
||||||
|
let (input, routing_key) = domain_shortstr(input)?;
|
||||||
|
Ok((input, Class::Basic(Basic::Return {
|
||||||
|
reply_code,
|
||||||
|
reply_text,
|
||||||
|
exchange,
|
||||||
|
routing_key,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn basic_deliver(input: &[u8]) -> IResult<Class> {
|
fn basic_deliver(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([60])(input)?;
|
let (input, _) = tag([60])(input)?;
|
||||||
todo!()
|
let (input, consumer_tag) = domain_consumer_tag(input)?;
|
||||||
|
let (input, delivery_tag) = domain_delivery_tag(input)?;
|
||||||
|
let (input, bits) = bit(input, 1)?;
|
||||||
|
let redelivered = bits[0];
|
||||||
|
let (input, exchange) = domain_exchange_name(input)?;
|
||||||
|
let (input, routing_key) = domain_shortstr(input)?;
|
||||||
|
Ok((input, Class::Basic(Basic::Deliver {
|
||||||
|
consumer_tag,
|
||||||
|
delivery_tag,
|
||||||
|
redelivered,
|
||||||
|
exchange,
|
||||||
|
routing_key,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn basic_get(input: &[u8]) -> IResult<Class> {
|
fn basic_get(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([70])(input)?;
|
let (input, _) = tag([70])(input)?;
|
||||||
todo!()
|
let (input, reserved_1) = domain_short(input)?;
|
||||||
|
let (input, queue) = domain_queue_name(input)?;
|
||||||
|
let (input, bits) = bit(input, 1)?;
|
||||||
|
let no_ack = bits[0];
|
||||||
|
Ok((input, Class::Basic(Basic::Get {
|
||||||
|
reserved_1,
|
||||||
|
queue,
|
||||||
|
no_ack,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn basic_get_ok(input: &[u8]) -> IResult<Class> {
|
fn basic_get_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([71])(input)?;
|
let (input, _) = tag([71])(input)?;
|
||||||
todo!()
|
let (input, delivery_tag) = domain_delivery_tag(input)?;
|
||||||
|
let (input, bits) = bit(input, 1)?;
|
||||||
|
let redelivered = bits[0];
|
||||||
|
let (input, exchange) = domain_exchange_name(input)?;
|
||||||
|
let (input, routing_key) = domain_shortstr(input)?;
|
||||||
|
let (input, message_count) = domain_message_count(input)?;
|
||||||
|
Ok((input, Class::Basic(Basic::GetOk {
|
||||||
|
delivery_tag,
|
||||||
|
redelivered,
|
||||||
|
exchange,
|
||||||
|
routing_key,
|
||||||
|
message_count,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn basic_get_empty(input: &[u8]) -> IResult<Class> {
|
fn basic_get_empty(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([72])(input)?;
|
let (input, _) = tag([72])(input)?;
|
||||||
todo!()
|
let (input, reserved_1) = domain_shortstr(input)?;
|
||||||
|
Ok((input, Class::Basic(Basic::GetEmpty {
|
||||||
|
reserved_1,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn basic_ack(input: &[u8]) -> IResult<Class> {
|
fn basic_ack(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([80])(input)?;
|
let (input, _) = tag([80])(input)?;
|
||||||
todo!()
|
let (input, delivery_tag) = domain_delivery_tag(input)?;
|
||||||
|
let (input, bits) = bit(input, 1)?;
|
||||||
|
let multiple = bits[0];
|
||||||
|
Ok((input, Class::Basic(Basic::Ack {
|
||||||
|
delivery_tag,
|
||||||
|
multiple,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn basic_reject(input: &[u8]) -> IResult<Class> {
|
fn basic_reject(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([90])(input)?;
|
let (input, _) = tag([90])(input)?;
|
||||||
todo!()
|
let (input, delivery_tag) = domain_delivery_tag(input)?;
|
||||||
|
let (input, bits) = bit(input, 1)?;
|
||||||
|
let requeue = bits[0];
|
||||||
|
Ok((input, Class::Basic(Basic::Reject {
|
||||||
|
delivery_tag,
|
||||||
|
requeue,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn basic_recover_async(input: &[u8]) -> IResult<Class> {
|
fn basic_recover_async(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([100])(input)?;
|
let (input, _) = tag([100])(input)?;
|
||||||
todo!()
|
let (input, bits) = bit(input, 1)?;
|
||||||
|
let requeue = bits[0];
|
||||||
|
Ok((input, Class::Basic(Basic::RecoverAsync {
|
||||||
|
requeue,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn basic_recover(input: &[u8]) -> IResult<Class> {
|
fn basic_recover(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([110])(input)?;
|
let (input, _) = tag([110])(input)?;
|
||||||
todo!()
|
let (input, bits) = bit(input, 1)?;
|
||||||
|
let requeue = bits[0];
|
||||||
|
Ok((input, Class::Basic(Basic::Recover {
|
||||||
|
requeue,
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn basic_recover_ok(input: &[u8]) -> IResult<Class> {
|
fn basic_recover_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([111])(input)?;
|
let (input, _) = tag([111])(input)?;
|
||||||
todo!()
|
Ok((input, Class::Basic(Basic::RecoverOk {
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn tx(input: &[u8]) -> IResult<Class> {
|
fn tx(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([90])(input)?;
|
let (input, _) = tag([90])(input)?;
|
||||||
alt((
|
alt((tx_select, tx_select_ok, tx_commit, tx_commit_ok, tx_rollback, tx_rollback_ok))(input)
|
||||||
tx_select,
|
|
||||||
tx_select_ok,
|
|
||||||
tx_commit,
|
|
||||||
tx_commit_ok,
|
|
||||||
tx_rollback,
|
|
||||||
tx_rollback_ok,
|
|
||||||
))(input)
|
|
||||||
}
|
}
|
||||||
fn tx_select(input: &[u8]) -> IResult<Class> {
|
fn tx_select(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([10])(input)?;
|
let (input, _) = tag([10])(input)?;
|
||||||
todo!()
|
Ok((input, Class::Tx(Tx::Select {
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn tx_select_ok(input: &[u8]) -> IResult<Class> {
|
fn tx_select_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([11])(input)?;
|
let (input, _) = tag([11])(input)?;
|
||||||
todo!()
|
Ok((input, Class::Tx(Tx::SelectOk {
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn tx_commit(input: &[u8]) -> IResult<Class> {
|
fn tx_commit(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([20])(input)?;
|
let (input, _) = tag([20])(input)?;
|
||||||
todo!()
|
Ok((input, Class::Tx(Tx::Commit {
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn tx_commit_ok(input: &[u8]) -> IResult<Class> {
|
fn tx_commit_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([21])(input)?;
|
let (input, _) = tag([21])(input)?;
|
||||||
todo!()
|
Ok((input, Class::Tx(Tx::CommitOk {
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn tx_rollback(input: &[u8]) -> IResult<Class> {
|
fn tx_rollback(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([30])(input)?;
|
let (input, _) = tag([30])(input)?;
|
||||||
todo!()
|
Ok((input, Class::Tx(Tx::Rollback {
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
fn tx_rollback_ok(input: &[u8]) -> IResult<Class> {
|
fn tx_rollback_ok(input: &[u8]) -> IResult<Class> {
|
||||||
let (input, _) = tag([31])(input)?;
|
let (input, _) = tag([31])(input)?;
|
||||||
todo!()
|
Ok((input, Class::Tx(Tx::RollbackOk {
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
use crate::classes::generated::Class;
|
||||||
|
use crate::error::{ConException, ProtocolError, TransError};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
mod generated;
|
mod generated;
|
||||||
|
|
@ -5,6 +7,7 @@ mod parse_helper;
|
||||||
|
|
||||||
pub type Table = HashMap<String, FieldValue>;
|
pub type Table = HashMap<String, FieldValue>;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum FieldValue {
|
pub enum FieldValue {
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
ShortShortInt(i8),
|
ShortShortInt(i8),
|
||||||
|
|
@ -25,3 +28,19 @@ pub enum FieldValue {
|
||||||
FieldTable(Table),
|
FieldTable(Table),
|
||||||
Void,
|
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ pub fn long(input: &[u8]) -> IResult<Long> {
|
||||||
pub fn longlong(input: &[u8]) -> IResult<Longlong> {
|
pub fn longlong(input: &[u8]) -> IResult<Longlong> {
|
||||||
todo!()
|
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>> {
|
pub fn bit(input: &[u8], amount: u8) -> IResult<Vec<Bit>> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::error::{ProtocolError, TransError};
|
use crate::error::{ProtocolError, TransError};
|
||||||
use crate::frame;
|
use crate::frame;
|
||||||
|
use crate::frame::FrameType;
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
|
|
@ -27,6 +28,10 @@ impl Connection {
|
||||||
loop {
|
loop {
|
||||||
let frame = frame::read_frame(&mut self.stream, 10000).await?;
|
let frame = frame::read_frame(&mut self.stream, 10000).await?;
|
||||||
debug!(?frame, "received frame");
|
debug!(?frame, "received frame");
|
||||||
|
if frame.kind == FrameType::Method {
|
||||||
|
let class = super::classes::parse_method(&frame.payload)?;
|
||||||
|
debug!(?class, "was method frame");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,10 @@ mod frame_type {
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct Frame {
|
pub struct Frame {
|
||||||
/// The type of the frame including its parsed metadata.
|
/// The type of the frame including its parsed metadata.
|
||||||
kind: FrameType,
|
pub kind: FrameType,
|
||||||
channel: u16,
|
pub channel: u16,
|
||||||
/// Includes the whole payload, also including the metadata from each type.
|
/// Includes the whole payload, also including the metadata from each type.
|
||||||
payload: Vec<u8>,
|
pub payload: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
|
@ -29,23 +29,6 @@ pub enum FrameType {
|
||||||
Heartbeat = 8,
|
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>
|
pub async fn read_frame<R>(r: &mut R, max_frame_size: usize) -> Result<Frame, TransError>
|
||||||
where
|
where
|
||||||
R: AsyncReadExt + Unpin,
|
R: AsyncReadExt + Unpin,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue