-
-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Right way to imply a checksum #302
Comments
Are you able to provide an example of what you have and what you expect? I don't want to make assumptions on your format :) |
Actually the protocol definition is available on GitHub: https://github.com/Livox-SDK/Livox-SDK/wiki/Livox-SDK-Communication-Protocol#21-frame-format My current code is like this: #[deku_derive(DekuRead, DekuWrite)]
#[derive(Debug)]
#[deku(magic = b"\xAA")]
pub struct DekuControlFrame {
// /// Starting Byte, Fixed to be 0xAA
// #[deku(temp)]
// #[deku(assert_eq = "0xAA")]
// magic: u8,
/// Protocol Version, 1 for The Current Version
pub version: u8,
/// Length of The Frame, Max Value: 1400
// #[deku(temp)]
length: u16,
/// Command Type:
/// 0x00: CMD
/// 0x01: ACK
/// 0x02: MSG
// #[deku(temp)]
cmd_type: u8,
/// Frame Sequence Number
pub seq_num: u16,
/// Frame Header Checksum
// #[deku(temp)]
#[deku(
// bits = "16",
writer = "checksum_write_16(deku::output)"
)]
crc_16: u16,
/// Payload Data
#[deku(ctx = "*cmd_type")]
// #[deku(count = "cmd_type")]
pub data: FrameData,
/// Whole Frame Checksum
// #[deku(temp)]
#[deku(
// bits = "32",
writer = "checksum_write_32(deku::output)"
)]
crc_32: u32,
}
fn checksum_write_16(
output: &mut BitVec<u8, Msb0>,
) -> Result<(), DekuError> {
// writeln!()
// dbg!(&output);
CRC16.checksum(
output.as_raw_slice()
).write(output, ())
}
fn checksum_write_32(
output: &mut BitVec<u8, Msb0>,
) -> Result<(), DekuError> {
CRC32.checksum(
output.as_raw_slice()
).write(output, ())
} |
This looks okay to me...
what do you mean by this? Here's an example, it may help you. If you can provide a minimal reproduction that I can run I may be able to help debug. use deku::bitvec::{BitVec, Msb0};
use deku::prelude::*;
use std::convert::TryInto;
#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
struct DekuTest {
a: u8,
b: u8,
#[deku(writer = "checksum1(deku::output)")]
sum1: u16,
#[deku(count = "2")]
data: Vec<u8>,
#[deku(writer = "checksum2(deku::output)")]
sum2: u32,
}
fn checksum1(output: &mut BitVec<u8, Msb0>) -> Result<(), DekuError> {
let sum: u16 = output.as_raw_slice().iter().map(|v| *v as u16).sum();
sum.write(output, ())
}
fn checksum2(output: &mut BitVec<u8, Msb0>) -> Result<(), DekuError> {
let sum: u32 = output.as_raw_slice().iter().map(|v| *v as u32).sum();
sum.write(output, ())
}
fn main() {
let test_data: &[u8] = [
1, 2, // a and b as u8
3, 0, // sum1 as u16 little endian (1+2 == 3)
1, 2, // data as u8
9, 0, 0, 0 // sum2 as u32 little endian (1+2+3+1+2 == 9)
].as_ref();
let (_rest, ret_read) = DekuTest::from_bytes((test_data, 0)).unwrap();
assert_eq!(
ret_read,
DekuTest {
a: 1,
b: 2,
sum1: 3,
data: vec![1, 2],
sum2: 9
}
);
let ret_write: Vec<u8> = ret_read.try_into().unwrap();
assert_eq!(test_data.to_vec(), ret_write);
} |
Well, I want to hide the checksum or make it unchangeable (by using |
Ah interesting use case! Thanks for explaining furthur. I created a branch with some changes to be able to use You can try it out by changing the dependency: deku = { git = "https://github.com/sharksforarms/deku.git", branch = "sharksforarms/temp-write" } Here is the new example I came up with. Let me know if this matches your use-case. use deku::bitvec::{BitVec, Msb0};
use deku::prelude::*;
use std::convert::TryInto;
#[deku_derive(DekuRead, DekuWrite)]
#[derive(Debug, PartialEq)]
struct DekuTest {
a: u8,
b: u8,
#[deku(writer = "checksum1(deku::output)")]
#[deku(temp)]
sum1: (),
#[deku(count = "2")]
data: Vec<u8>,
#[deku(writer = "checksum2(deku::output)")]
#[deku(temp)]
sum2: (),
}
fn checksum1(output: &mut BitVec<u8, Msb0>) -> Result<(), DekuError> {
let sum: u16 = output.as_raw_slice().iter().map(|v| *v as u16).sum();
sum.write(output, ())
}
fn checksum2(output: &mut BitVec<u8, Msb0>) -> Result<(), DekuError> {
let sum: u32 = output.as_raw_slice().iter().map(|v| *v as u32).sum();
sum.write(output, ())
}
fn main() {
let test_data_read: &[u8] = [
1, 2, // a and b as u8
1, 2, // data as u8
]
.as_ref();
let test_data_write: &[u8] = [
1, 2, // a and b as u8
3, 0, // sum1 as u16 little endian (1+2 == 3)
1, 2, // data as u8
9, 0, 0, 0, // sum2 as u32 little endian (1+2+3+1+2 == 9)
]
.as_ref();
let (_rest, ret_read) = DekuTest::from_bytes((test_data_read, 0)).unwrap();
assert_eq!(
ret_read,
DekuTest {
a: 1,
b: 2,
data: vec![1, 2],
}
);
let ret_write: Vec<u8> = ret_read.try_into().unwrap();
assert_eq!(test_data_write.to_vec(), ret_write);
} |
Wow, thanks for the amazing job! It works just like how I imagined. By the way, is it possible to make context parameter PPS. What about the |
The thing with |
Hello, I wonder if sharksforarms/temp-write is going to be merged to main? |
Did this MR fix your issues? #322 |
Sorry, I haven't been around this project until now 😢 And I found a bug when using it with context( My code: #[deku(temp, temp_value = "self.data.deku_id()?")]
pub cmd_id: u16,
#[deku(ctx = "*cmd_id, *cmd_type")]
pub data: command::Data, Expands to: While I could simply change type in |
Would this be a minimal reproduction? use deku::prelude::*;
use std::convert::TryInto;
#[deku_derive(DekuRead, DekuWrite)]
#[derive(Debug, PartialEq)]
#[deku(ctx = "field1: u8, field2: u8")]
struct Child {
}
#[deku_derive(DekuRead, DekuWrite)]
#[derive(Debug, PartialEq)]
struct Parent {
pub field1: u8,
#[deku(temp, temp_value = "self.field1")]
pub field2: u8,
#[deku(ctx = "*field1, *field2")]
pub field3: Child
}
fn main() {
let value = Parent {
field1: 0x01,
field3: Child {}
};
let value: Vec<u8> = value.try_into().unwrap();
assert_eq!(vec![0x01], value);
} I don't have time to work on this at the moment, cc: @SneakyBerry maybe they have ideas |
@sharksforarms thanks for mentioning and minimal reproduction. I'll do some research and provide MR. |
@SneakyBerry Hello, have you get any progress there? |
@shirok1 Hi! Check this. Will it work for you? |
Hello, I've been porting a network protocol to Rust using
deku
recently, replacing handwritten macros. In this protocol, there are two checksum fields, one is a CRC16 for header and one is a CRC32 in the tail. I tried using custom writer withtemp
tag, result in the field being completely ignored during writing. I also tried usingbits = "16"
orpad_bits_after = "16"
with a()
type, but the corresponding bytes are not jumped. Is there a best practice to imply such thing?The text was updated successfully, but these errors were encountered: