Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0d76d94

Browse files
committed
Replaced dump parsing code with a Regex
1 parentdfa0b88 commit0d76d94

File tree

2 files changed

+61
-73
lines changed

2 files changed

+61
-73
lines changed

‎Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Linux SocketCAN library. Send and receive CAN frames via CANbus on Linux.
2626
[features]
2727
default = ["netlink","dump"]
2828
netlink = ["neli"]
29-
dump = []
29+
dump = ["regex","lazy_static"]
3030
netlink_tests = ["netlink"]
3131
vcan_tests = ["netlink"]
3232
utils = ["clap","anyhow"]
@@ -55,6 +55,8 @@ async-io = { version = "1.13", optional = true }
5555
smol = {version ="1.3",optional =true }
5656
async-std = {version ="1.12",optional =true }
5757
libudev = {version ="0.3",optional =true }
58+
regex = {version ="1.11",optional =true }
59+
lazy_static = {version ="1.5",optional =true }
5860

5961
# This hack avoids building neli on non-linux platforms, which
6062
# avoids a ton of compile errors. Worthwhile together with the

‎src/dump.rs

Lines changed: 58 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,15 @@ use crate::{
2929
};
3030
use embedded_can::StandardId;
3131
use hex::FromHex;
32+
use lazy_static::lazy_static;
3233
use libc::canid_t;
33-
use std::{fs, io, path, str};
34-
35-
// cannot be generic, because from_str_radix is not part of any Trait
36-
fnparse_raw(bytes:&[u8],radix:u32) ->Option<u64>{
37-
str::from_utf8(bytes)
38-
.ok()
39-
.and_then(|s| u64::from_str_radix(s, radix).ok())
40-
}
34+
use regex::Regex;
35+
use std::{
36+
fs::File,
37+
io::{self,BufRead,BufReader},
38+
path::Path,
39+
str,
40+
};
4141

4242
#[derive(Debug)]
4343
/// A CAN log reader.
@@ -48,21 +48,18 @@ pub struct Reader<R> {
4848

4949
impl<R: io::Read>Reader<R>{
5050
/// Creates an I/O buffered reader from a CAN log reader.
51-
pubfnfrom_reader(rdr:R) ->Reader<io::BufReader<R>>{
51+
pubfnfrom_reader(rdr:R) ->Reader<BufReader<R>>{
5252
Reader{
53-
rdr:io::BufReader::new(rdr),
53+
rdr:BufReader::new(rdr),
5454
line_buf:Vec::new(),
5555
}
5656
}
5757
}
5858

59-
implReader<fs::File>{
59+
implReader<File>{
6060
/// Creates an I/O buffered reader from a file.
61-
pubfnfrom_file<P>(path:P) -> io::Result<Reader<io::BufReader<fs::File>>>
62-
where
63-
P:AsRef<path::Path>,
64-
{
65-
Ok(Reader::from_reader(fs::File::open(path)?))
61+
pubfnfrom_file<P:AsRef<Path>>(path:P) -> io::Result<Reader<BufReader<File>>>{
62+
Ok(Reader::from_reader(File::open(path)?))
6663
}
6764
}
6865

@@ -112,7 +109,14 @@ impl From<ConstructionError> for ParseError {
112109
}
113110
}
114111

115-
impl<R: io::BufRead>Reader<R>{
112+
lazy_static!{
113+
// Matches a candump line
114+
static refRE_DUMP:Regex =Regex::new(
115+
r"\s*\((?P<t_num>[0-9]+)\.(?P<t_mant>[0-9]*)\)\s+(?P<iface>\w+)\s+(?P<can_id>[0-9A-Fa-f]+)(((?P<fd_sep>\#\#)(?P<fd_flags>[0-9A-Fa-f]))|(?P<sep>\#))(?P<data>[0-9A-Fa-f\s]*)"
116+
).unwrap();
117+
}
118+
119+
impl<R:BufRead>Reader<R>{
116120
/// Returns an iterator over all records
117121
pubfnrecords(&mutself) ->CanDumpRecords<R>{
118122
CanDumpRecords{src:self}
@@ -123,83 +127,65 @@ impl<R: io::BufRead> Reader<R> {
123127
self.line_buf.clear();
124128
let bytes_read =self.rdr.read_until(b'\n',&mutself.line_buf)?;
125129

126-
// reached EOF
127130
if bytes_read ==0{
128131
returnOk(None);
129132
}
130133

131-
letmut field_iter =self.line_buf.split(|&c| c ==b' ');
134+
let line = str::from_utf8(&self.line_buf[..bytes_read])
135+
.map_err(|_|ParseError::InvalidCanFrame)?;
132136

133-
// parse time field
134-
let f = field_iter.next().ok_or(ParseError::UnexpectedEndOfLine)?;
137+
let caps =RE_DUMP
138+
.captures(line)
139+
.ok_or(ParseError::UnexpectedEndOfLine)?;
135140

136-
if f.len() <3 || f[0] !=b'(' || f[f.len() -1] !=b')'{
137-
returnErr(ParseError::InvalidTimestamp);
138-
}
139-
140-
let inner =&f[1..f.len() -1];
141-
142-
// split at dot, read both parts
143-
let dot = inner
144-
.iter()
145-
.position(|&c| c ==b'.')
141+
let t_num:u64 = caps
142+
.name("t_num")
143+
.and_then(|m| m.as_str().parse::<u64>().ok())
146144
.ok_or(ParseError::InvalidTimestamp)?;
147145

148-
let(num, mant) = inner.split_at(dot);
149-
150-
// parse number and multiply
151-
let n_num:u64 =parse_raw(num,10).ok_or(ParseError::InvalidTimestamp)?;
152-
let n_mant:u64 =parse_raw(&mant[1..],10).ok_or(ParseError::InvalidTimestamp)?;
153-
let t_us = n_num.saturating_mul(1_000_000).saturating_add(n_mant);
146+
let t_mant:u64 = caps
147+
.name("t_mant")
148+
.and_then(|m| m.as_str().parse::<u64>().ok())
149+
.ok_or(ParseError::InvalidTimestamp)?;
154150

155-
letf =field_iter.next().ok_or(ParseError::UnexpectedEndOfLine)?;
151+
lett_us =t_num.saturating_mul(1_000_000).saturating_add(t_mant);
156152

157-
// device name
158-
let device = str::from_utf8(f).map_err(|_|ParseError::InvalidDeviceName)?;
153+
let device = caps
154+
.name("iface")
155+
.map(|m| m.as_str())
156+
//.map(String::from)
157+
.ok_or(ParseError::InvalidDeviceName)?;
159158

160-
// parse packet
161-
let can_raw = field_iter.next().ok_or(ParseError::UnexpectedEndOfLine)?;
159+
let is_fd_frame = caps.name("fd_sep").is_some();
162160

163-
letsep_idx = can_raw
164-
.iter()
165-
.position(|&c| c ==b'#')
161+
letmut can_id:canid_t = caps
162+
.name("can_id")
163+
.and_then(|m| canid_t::from_str_radix(m.as_str(),16).ok())
166164
.ok_or(ParseError::InvalidCanFrame)?;
167-
let(can_id_str,mut can_data) = can_raw.split_at(sep_idx);
168-
169-
// determine frame type (FD or classical) and skip separator(s)
170-
letmut fd_flags =FdFlags::empty();
171-
let is_fd_frame =ifletSome(&b'#') = can_data.get(1){
172-
fd_flags =FdFlags::from_bits_truncate(can_data[2]);
173-
can_data =&can_data[3..];
174-
true
175-
}else{
176-
can_data =&can_data[1..];
177-
false
178-
};
179165

180-
// cut of linefeed
181-
ifletSome(&b'\n') = can_data.last(){
182-
can_data =&can_data[..can_data.len() -1];
183-
};
184-
// cut off \r
185-
ifletSome(&b'\r') = can_data.last(){
186-
can_data =&can_data[..can_data.len() -1];
187-
};
166+
let can_data = caps
167+
.name("data")
168+
.map(|m| m.as_str().trim())
169+
.ok_or(ParseError::InvalidCanFrame)?;
188170

189-
letmut can_id =(parse_raw(can_id_str,16).ok_or(ParseError::InvalidCanFrame)?)ascanid_t;
190171
letmut id_flags =IdFlags::empty();
191-
id_flags.set(IdFlags::RTR,b"R" == can_data);
172+
id_flags.set(IdFlags::RTR,"R" == can_data);
192173
id_flags.set(IdFlags::EFF, can_id >=StandardId::MAX.as_raw()ascanid_t);
193174
// TODO: How are error frames saved?
194175
can_id |= id_flags.bits();
195176

196-
let data =if id_flags.contains(IdFlags::RTR){
197-
vec![]
198-
}else{
199-
Vec::from_hex(can_data).map_err(|_|ParseError::InvalidCanFrame)?
177+
let data =match id_flags.contains(IdFlags::RTR){
178+
true =>vec![],
179+
false =>Vec::from_hex(can_data).map_err(|_|ParseError::InvalidCanFrame)?,
200180
};
201181

202182
let frame:CanAnyFrame =if is_fd_frame{
183+
let fd_flags:FdFlags = caps
184+
.name("fd_flags")
185+
.and_then(|m| u8::from_str_radix(m.as_str(),16).ok())
186+
.map(FdFlags::from_bits_truncate)
187+
.ok_or(ParseError::InvalidCanFrame)?;
188+
203189
CanFdFrame::init(can_id,&data, fd_flags).map(CanAnyFrame::Fd)
204190
}else{
205191
CanDataFrame::init(can_id,&data)
@@ -215,7 +201,7 @@ impl<R: io::BufRead> Reader<R> {
215201
}
216202
}
217203

218-
impl<R: io::Read>IteratorforCanDumpRecords<'_,io::BufReader<R>>{
204+
impl<R: io::Read>IteratorforCanDumpRecords<'_,BufReader<R>>{
219205
typeItem =Result<(u64,CanAnyFrame),ParseError>;
220206

221207
fnnext(&mutself) ->Option<Self::Item>{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp