mirror of
https://github.com/Noratrieb/haesli.git
synced 2026-01-16 20:55:03 +01:00
big future
This commit is contained in:
parent
2aeb588ab3
commit
fcf531df43
8 changed files with 1405 additions and 1297 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,3 @@
|
|||
use crate::classes::generated::Class;
|
||||
use crate::error::{ConException, ProtocolError, TransError};
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
|
@ -35,7 +34,7 @@ pub enum FieldValue {
|
|||
pub use generated::*;
|
||||
|
||||
/// Parses the payload of a method frame into the class/method
|
||||
pub fn parse_method(payload: &[u8]) -> Result<Class, TransError> {
|
||||
pub fn parse_method(payload: &[u8]) -> Result<generated::Class, TransError> {
|
||||
let nom_result = generated::parse::parse_method(payload);
|
||||
|
||||
match nom_result {
|
||||
|
|
|
|||
|
|
@ -1,33 +1,32 @@
|
|||
use crate::classes::generated::{
|
||||
Bit, Long, Longlong, Longstr, Octet, Short, Shortstr, Table, Timestamp,
|
||||
};
|
||||
use crate::classes::{FieldValue, TableFieldName};
|
||||
use crate::error::TransError;
|
||||
use crate::classes::FieldValue;
|
||||
use crate::classes::{Bit, Long, Longlong, Longstr, Octet, Short, Shortstr, Table, Timestamp};
|
||||
use crate::error::Result;
|
||||
use anyhow::Context;
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
|
||||
pub fn octet<W: Write>(value: Octet, writer: &mut W) -> Result<(), TransError> {
|
||||
writer.write_all(&[value])?;
|
||||
pub async fn octet<W: AsyncWriteExt + Unpin>(value: Octet, writer: &mut W) -> Result<()> {
|
||||
writer.write_u8(value).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn short<W: Write>(value: Short, writer: &mut W) -> Result<(), TransError> {
|
||||
writer.write_all(&value.to_be_bytes())?;
|
||||
pub async fn short<W: AsyncWriteExt + Unpin>(value: Short, writer: &mut W) -> Result<()> {
|
||||
writer.write_u16(value).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn long<W: Write>(value: Long, writer: &mut W) -> Result<(), TransError> {
|
||||
writer.write_all(&value.to_be_bytes())?;
|
||||
pub async fn long<W: AsyncWriteExt + Unpin>(value: Long, writer: &mut W) -> Result<()> {
|
||||
writer.write_u32(value).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn longlong<W: Write>(value: Longlong, writer: &mut W) -> Result<(), TransError> {
|
||||
writer.write_all(&value.to_be_bytes())?;
|
||||
pub async fn longlong<W: AsyncWriteExt + Unpin>(value: Longlong, writer: &mut W) -> Result<()> {
|
||||
writer.write_u64(value).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn bit<W: Write>(value: &[Bit], writer: &mut W) -> Result<(), TransError> {
|
||||
pub async fn bit<W: AsyncWriteExt + Unpin>(value: &[Bit], writer: &mut W) -> Result<()> {
|
||||
// accumulate bits into bytes, starting from the least significant bit in each byte
|
||||
|
||||
// how many bits have already been packed into `current_buf`
|
||||
|
|
@ -36,7 +35,7 @@ pub fn bit<W: Write>(value: &[Bit], writer: &mut W) -> Result<(), TransError> {
|
|||
|
||||
for &bit in value {
|
||||
if already_filled >= 8 {
|
||||
writer.write_all(&[current_buf])?;
|
||||
writer.write_u8(current_buf).await?;
|
||||
current_buf = 0;
|
||||
already_filled = 0;
|
||||
}
|
||||
|
|
@ -47,146 +46,151 @@ pub fn bit<W: Write>(value: &[Bit], writer: &mut W) -> Result<(), TransError> {
|
|||
}
|
||||
|
||||
if already_filled > 0 {
|
||||
writer.write_all(&[current_buf])?;
|
||||
writer.write_u8(current_buf).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn shortstr<W: Write>(value: Shortstr, writer: &mut W) -> Result<(), TransError> {
|
||||
pub async fn shortstr<W: AsyncWriteExt + Unpin>(value: Shortstr, writer: &mut W) -> Result<()> {
|
||||
let len = u8::try_from(value.len()).context("shortstr too long")?;
|
||||
writer.write_all(&[len])?;
|
||||
writer.write_all(value.as_bytes())?;
|
||||
writer.write_u8(len).await?;
|
||||
writer.write_all(value.as_bytes()).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn longstr<W: Write>(value: Longstr, writer: &mut W) -> Result<(), TransError> {
|
||||
pub async fn longstr<W: AsyncWriteExt + Unpin>(value: Longstr, writer: &mut W) -> Result<()> {
|
||||
let len = u32::try_from(value.len()).context("longstr too long")?;
|
||||
writer.write_all(&len.to_be_bytes())?;
|
||||
writer.write_all(value.as_slice())?;
|
||||
writer.write_u32(len).await?;
|
||||
writer.write_all(value.as_slice()).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn timestamp<W: Write>(value: Timestamp, writer: &mut W) -> Result<(), TransError> {
|
||||
writer.write_all(&value.to_be_bytes())?;
|
||||
pub async fn timestamp<W: AsyncWriteExt + Unpin>(value: Timestamp, writer: &mut W) -> Result<()> {
|
||||
writer.write_u64(value).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn table<W: Write>(table: Table, writer: &mut W) -> Result<(), TransError> {
|
||||
pub async fn table<W: AsyncWriteExt + Unpin>(table: Table, writer: &mut W) -> Result<()> {
|
||||
let len = u32::try_from(table.len()).context("table too big")?;
|
||||
writer.write_all(&len.to_be_bytes())?;
|
||||
writer.write_u32(len).await?;
|
||||
|
||||
for (field_name, value) in table {
|
||||
shortstr(field_name, writer)?;
|
||||
field_value(value, writer)?;
|
||||
shortstr(field_name, writer).await?;
|
||||
field_value(value, writer).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn field_value<W: Write>(value: FieldValue, writer: &mut W) -> Result<(), TransError> {
|
||||
match value {
|
||||
FieldValue::Boolean(bool) => {
|
||||
writer.write_all(&[b't', u8::from(bool)])?;
|
||||
}
|
||||
FieldValue::ShortShortInt(int) => {
|
||||
writer.write_all(b"b")?;
|
||||
writer.write_all(&int.to_be_bytes())?;
|
||||
}
|
||||
FieldValue::ShortShortUInt(int) => {
|
||||
writer.write_all(&[b'B', int])?;
|
||||
}
|
||||
FieldValue::ShortInt(int) => {
|
||||
writer.write_all(b"U")?;
|
||||
writer.write_all(&int.to_be_bytes())?;
|
||||
}
|
||||
FieldValue::ShortUInt(int) => {
|
||||
writer.write_all(b"u")?;
|
||||
writer.write_all(&int.to_be_bytes())?;
|
||||
}
|
||||
FieldValue::LongInt(int) => {
|
||||
writer.write_all(b"I")?;
|
||||
writer.write_all(&int.to_be_bytes())?;
|
||||
}
|
||||
FieldValue::LongUInt(int) => {
|
||||
writer.write_all(b"i")?;
|
||||
writer.write_all(&int.to_be_bytes())?;
|
||||
}
|
||||
FieldValue::LongLongInt(int) => {
|
||||
writer.write_all(b"L")?;
|
||||
writer.write_all(&int.to_be_bytes())?;
|
||||
}
|
||||
FieldValue::LongLongUInt(int) => {
|
||||
writer.write_all(b"l")?;
|
||||
writer.write_all(&int.to_be_bytes())?;
|
||||
}
|
||||
FieldValue::Float(float) => {
|
||||
writer.write_all(b"f")?;
|
||||
writer.write_all(&float.to_be_bytes())?;
|
||||
}
|
||||
FieldValue::Double(float) => {
|
||||
writer.write_all(b"d")?;
|
||||
writer.write_all(&float.to_be_bytes())?;
|
||||
}
|
||||
FieldValue::DecimalValue(scale, long) => {
|
||||
writer.write_all(&[b'D', scale])?;
|
||||
writer.write_all(&long.to_be_bytes())?;
|
||||
}
|
||||
FieldValue::ShortString(str) => {
|
||||
writer.write_all(b"s")?;
|
||||
shortstr(str, writer)?;
|
||||
}
|
||||
FieldValue::LongString(str) => {
|
||||
writer.write_all(b"S")?;
|
||||
longstr(str, writer)?;
|
||||
}
|
||||
FieldValue::FieldArray(array) => {
|
||||
writer.write_all(b"A")?;
|
||||
let len = u32::try_from(array.len()).context("array too long")?;
|
||||
writer.write_all(&len.to_be_bytes())?;
|
||||
fn field_value<W: AsyncWriteExt + Unpin>(
|
||||
value: FieldValue,
|
||||
writer: &mut W,
|
||||
) -> Pin<Box<dyn Future<Output = Result<()>> + '_>> {
|
||||
Box::pin(async {
|
||||
match value {
|
||||
FieldValue::Boolean(bool) => {
|
||||
writer.write_all(&[b't', u8::from(bool)]).await?;
|
||||
}
|
||||
FieldValue::ShortShortInt(int) => {
|
||||
writer.write_all(b"b").await?;
|
||||
writer.write_all(&int.to_be_bytes()).await?;
|
||||
}
|
||||
FieldValue::ShortShortUInt(int) => {
|
||||
writer.write_all(&[b'B', int]).await?;
|
||||
}
|
||||
FieldValue::ShortInt(int) => {
|
||||
writer.write_all(b"U").await?;
|
||||
writer.write_all(&int.to_be_bytes()).await?;
|
||||
}
|
||||
FieldValue::ShortUInt(int) => {
|
||||
writer.write_all(b"u").await?;
|
||||
writer.write_all(&int.to_be_bytes()).await?;
|
||||
}
|
||||
FieldValue::LongInt(int) => {
|
||||
writer.write_all(b"I").await?;
|
||||
writer.write_all(&int.to_be_bytes()).await?;
|
||||
}
|
||||
FieldValue::LongUInt(int) => {
|
||||
writer.write_all(b"i").await?;
|
||||
writer.write_all(&int.to_be_bytes()).await?;
|
||||
}
|
||||
FieldValue::LongLongInt(int) => {
|
||||
writer.write_all(b"L").await?;
|
||||
writer.write_all(&int.to_be_bytes()).await?;
|
||||
}
|
||||
FieldValue::LongLongUInt(int) => {
|
||||
writer.write_all(b"l").await?;
|
||||
writer.write_all(&int.to_be_bytes()).await?;
|
||||
}
|
||||
FieldValue::Float(float) => {
|
||||
writer.write_all(b"f").await?;
|
||||
writer.write_all(&float.to_be_bytes()).await?;
|
||||
}
|
||||
FieldValue::Double(float) => {
|
||||
writer.write_all(b"d").await?;
|
||||
writer.write_all(&float.to_be_bytes()).await?;
|
||||
}
|
||||
FieldValue::DecimalValue(scale, long) => {
|
||||
writer.write_all(&[b'D', scale]).await?;
|
||||
writer.write_all(&long.to_be_bytes()).await?;
|
||||
}
|
||||
FieldValue::ShortString(str) => {
|
||||
writer.write_all(b"s").await?;
|
||||
shortstr(str, writer).await?;
|
||||
}
|
||||
FieldValue::LongString(str) => {
|
||||
writer.write_all(b"S").await?;
|
||||
longstr(str, writer).await?;
|
||||
}
|
||||
FieldValue::FieldArray(array) => {
|
||||
writer.write_all(b"A").await?;
|
||||
let len = u32::try_from(array.len()).context("array too long")?;
|
||||
writer.write_all(&len.to_be_bytes()).await?;
|
||||
|
||||
for element in array {
|
||||
field_value(element, writer)?;
|
||||
for element in array {
|
||||
field_value(element, writer).await?;
|
||||
}
|
||||
}
|
||||
FieldValue::Timestamp(time) => {
|
||||
writer.write_all(b"T").await?;
|
||||
writer.write_all(&time.to_be_bytes()).await?;
|
||||
}
|
||||
FieldValue::FieldTable(_) => {
|
||||
writer.write_all(b"F").await?;
|
||||
}
|
||||
FieldValue::Void => {
|
||||
writer.write_all(b"V").await?;
|
||||
}
|
||||
}
|
||||
FieldValue::Timestamp(time) => {
|
||||
writer.write_all(b"T")?;
|
||||
writer.write_all(&time.to_be_bytes())?;
|
||||
}
|
||||
FieldValue::FieldTable(_) => {
|
||||
writer.write_all(b"F")?;
|
||||
}
|
||||
FieldValue::Void => {
|
||||
writer.write_all(b"V")?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn pack_few_bits() {
|
||||
#[tokio::test]
|
||||
async fn pack_few_bits() {
|
||||
let bits = vec![true, false, true];
|
||||
|
||||
let mut buffer = [0u8; 1];
|
||||
super::bit(bits, &mut buffer.as_mut_slice()).unwrap();
|
||||
let mut buffer = Vec::new();
|
||||
super::bit(&bits, &mut buffer).await.unwrap();
|
||||
|
||||
assert_eq!(buffer, [0b00000101])
|
||||
assert_eq!(buffer.as_slice(), &[0b00000101])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pack_many_bits() {
|
||||
#[tokio::test]
|
||||
async fn pack_many_bits() {
|
||||
let bits = vec![
|
||||
/* first 8 */
|
||||
true, true, true, true, false, false, false, false, /* second 4 */
|
||||
true, false, true, true,
|
||||
];
|
||||
|
||||
let mut buffer = [0u8; 2];
|
||||
super::bit(bits, &mut buffer.as_mut_slice()).unwrap();
|
||||
let mut buffer = Vec::new();
|
||||
super::bit(&bits, &mut buffer).await.unwrap();
|
||||
|
||||
assert_eq!(buffer, [0b00001111, 0b00001101]);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue