Skip to content

Commit 7a78584

Browse files
committed
Parse the whole packet in one go
1 parent 2b81fe4 commit 7a78584

File tree

4 files changed

+24
-35
lines changed

4 files changed

+24
-35
lines changed

src/bin/test_parse.rs

+1-20
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ use std::error;
44

55
use winnow::{Bytes, Parser};
66

7-
use libmbus::parse::application_layer::frame::Frame;
87
use libmbus::parse::link_layer::Packet;
9-
use libmbus::parse::transport_layer::CICode;
108

119
fn do_file(fname: &str) -> Result<(), Box<dyn error::Error>> {
1210
let data = std::fs::read(fname).map_err(Box::new)?;
@@ -15,24 +13,7 @@ fn do_file(fname: &str) -> Result<(), Box<dyn error::Error>> {
1513
.parse(Bytes::new(&data[..]))
1614
.map_err(|e| e.into_inner().to_string())?;
1715

18-
println!("{packet:?}");
19-
20-
match packet {
21-
Packet::Long { data, .. } => {
22-
let mut data = Bytes::new(data);
23-
let ci = CICode::parse
24-
.parse_next(&mut data)
25-
.map_err(|e| e.to_string())?;
26-
println!("{ci:#?}");
27-
28-
let frame = Frame::parse
29-
.parse(data)
30-
.map_err(|e| e.into_inner().to_string())?;
31-
32-
println!("{frame:#?}");
33-
}
34-
_ => todo!(),
35-
}
16+
println!("{packet:#?}");
3617
Ok(())
3718
}
3819

src/parse/link_layer.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use winnow::stream::Stream;
1010
use winnow::Bytes;
1111

1212
use super::error::{MBResult, MBusError};
13+
use super::transport_layer::MBusMessage;
1314

1415
const LONG_FRAME_HEADER: u8 = 0x68;
1516
const SHORT_FRAME_HEADER: u8 = 0x10;
@@ -113,7 +114,7 @@ impl Control {
113114
}
114115

115116
#[derive(Debug)]
116-
pub enum Packet<'a> {
117+
pub enum Packet {
117118
Ack,
118119
Short {
119120
control: Control,
@@ -122,11 +123,11 @@ pub enum Packet<'a> {
122123
Long {
123124
control: Control,
124125
address: u8,
125-
data: &'a [u8],
126+
message: MBusMessage,
126127
},
127128
}
128129

129-
fn parse_variable<'a>(input: &mut &'a Bytes) -> MBResult<Packet<'a>> {
130+
fn parse_variable(input: &mut &Bytes) -> MBResult<Packet> {
130131
let length = binary::u8
131132
.context(StrContext::Label("length"))
132133
.parse_next(input)?;
@@ -183,14 +184,18 @@ fn parse_variable<'a>(input: &mut &'a Bytes) -> MBResult<Packet<'a>> {
183184
);
184185
}
185186

187+
let mut data = Bytes::new(data);
188+
189+
let message = MBusMessage::parse.parse_next(&mut data)?;
190+
186191
Ok(Packet::Long {
187192
control,
188193
address,
189-
data,
194+
message,
190195
})
191196
}
192197

193-
fn parse_fixed<'a>(input: &mut &'a Bytes) -> MBResult<Packet<'a>> {
198+
fn parse_fixed(input: &mut &Bytes) -> MBResult<Packet> {
194199
// mbus's fixed length datagrams are 2 bytes long, only control & address
195200
let ((control, raw_control), address, checksum, _) = (
196201
Control::parse
@@ -217,12 +222,12 @@ fn parse_fixed<'a>(input: &mut &'a Bytes) -> MBResult<Packet<'a>> {
217222
Ok(Packet::Short { control, address })
218223
}
219224

220-
fn parse_ack<'a>(_input: &mut &'a Bytes) -> MBResult<Packet<'a>> {
225+
fn parse_ack(_input: &mut &Bytes) -> MBResult<Packet> {
221226
Ok(Packet::Ack)
222227
}
223228

224-
impl<'a> Packet<'a> {
225-
pub fn parse(input: &mut &'a Bytes) -> MBResult<Packet<'a>> {
229+
impl<'a> Packet {
230+
pub fn parse(input: &mut &'a Bytes) -> MBResult<Packet> {
226231
alt((
227232
preceded(
228233
LONG_FRAME_HEADER.void(),

src/parse/transport_layer.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ pub mod control_info;
44
pub mod header;
55
pub mod manufacturer;
66

7-
pub use control_info::CICode;
7+
pub use control_info::MBusMessage;

src/parse/transport_layer/control_info.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use winnow::error::StrContext;
77
use winnow::prelude::*;
88
use winnow::Bytes;
99

10+
use crate::parse::application_layer::frame::Frame;
1011
use crate::parse::error::MBResult;
1112

1213
use super::header::LongHeader;
@@ -25,12 +26,12 @@ pub enum BaudRate {
2526
}
2627

2728
#[derive(Debug)]
28-
pub enum CICode {
29+
pub enum MBusMessage {
2930
Dlms(u8, TPLHeader), // TODO: Unsupported "see EN 13757–1"
3031
Reserved,
3132
ApplicationReset(TPLHeader), // or "Select To Device", EN 13757–3:2018, Clause 7
3233
CommandToDevice(TPLHeader), // EN 13757–3:2018, Clause 6
33-
ResponseFromDevice(TPLHeader), // EN 13757–3:2018, Clause 6, Annex G
34+
ResponseFromDevice(TPLHeader, Frame), // EN 13757–3:2018, Clause 6, Annex G
3435
SelectionOfDevice, // EN 13757-7:2018, Clause 8.4
3536
SelectedApplicationRequest(TPLHeader), // EN 13757–3:2018, Clause 7
3637
SelectedApplicationResponse(TPLHeader), // EN 13757–3:2018, Clause 7
@@ -48,16 +49,18 @@ pub enum CICode {
4849
SecurityTransfer(u8), // TODO: Unsupported - EN 13757–3:2018, Annex A
4950
}
5051

51-
impl CICode {
52-
pub fn parse(input: &mut &Bytes) -> MBResult<CICode> {
52+
impl MBusMessage {
53+
pub fn parse(input: &mut &Bytes) -> MBResult<MBusMessage> {
5354
let ci = binary::u8
5455
.context(StrContext::Label("CI field"))
5556
.parse_next(input)?;
5657

57-
let mut parse_long_header = LongHeader::parse.context(StrContext::Label("long header"));
58+
let parse_long_header = LongHeader::parse.context(StrContext::Label("long header"));
5859

5960
Ok(match ci {
60-
0x72 => CICode::ResponseFromDevice(parse_long_header.parse_next(input)?),
61+
0x72 => (parse_long_header, Frame::parse)
62+
.map(|(header, frame)| MBusMessage::ResponseFromDevice(header, frame))
63+
.parse_next(input)?,
6164
_ => todo!(),
6265
})
6366
}

0 commit comments

Comments
 (0)