pub enum SMLMessageBuilder {
Empty,
IncompleteStartSignature(usize),
Recording(Vec<u8>),
Complete {
data: Vec<u8>,
rest: Vec<u8>,
},
}Expand description
Builder to read SML messages byte-wise from a stream
use hackdose_sml_parser::transport::SMLMessageBuilder;
let mut builder = SMLMessageBuilder::Empty;
builder.record(&[0x1b, 0x1b, 0x1b, 0x1b, 0x01, 0x01, 0x01, 0x01]);
builder.record(&[0x63, 0x01, 0x02]);
builder.record(&[0x1b, 0x1b, 0x1b, 0x1b, 0x1a, 0x01,0x02, 0x03]);
assert_eq!(builder, SMLMessageBuilder::Complete{ data: vec![0x63, 0x01, 0x02], rest: vec![]});Variants§
Implementations§
source§impl SMLMessageBuilder
impl SMLMessageBuilder
sourcepub fn record(&mut self, buf: &[u8])
pub fn record(&mut self, buf: &[u8])
Examples found in repository?
src/message_stream/mod.rs (line 43)
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
async fn emit_message<'a>(
builder: &'a mut SMLMessageBuilder,
buf: &'a [u8],
tx: Sender<SmlMessages>,
) {
let mut to_process = buf.to_vec();
while to_process.len() > 0 {
builder.record(&to_process);
to_process = vec![];
match builder {
SMLMessageBuilder::Complete { ref data, ref rest } => {
let result = parse_body(data);
if let Ok(messages) = result {
let _ = tx.send(messages).await;
}
if rest.len() == 0 {
*builder = SMLMessageBuilder::Empty;
} else {
to_process = rest.to_vec();
*builder = SMLMessageBuilder::Empty;
}
}
SMLMessageBuilder::Empty => (),
SMLMessageBuilder::IncompleteStartSignature(_) => (),
SMLMessageBuilder::Recording(_) => (),
}
}
}More examples
src/transport/mod.rs (lines 75-79)
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
pub fn record(&mut self, buf: &[u8]) {
match self {
SMLMessageBuilder::Empty | SMLMessageBuilder::IncompleteStartSignature(_) => {
let start = match self {
SMLMessageBuilder::Empty => 0,
SMLMessageBuilder::IncompleteStartSignature(start) => *start,
SMLMessageBuilder::Recording(_) => todo!(),
SMLMessageBuilder::Complete { data: _, rest: _ } => todo!(),
};
let remainder_of_start_sequence = &START_SEQUENCE[start..];
let remaining_start_sequence_bytes = remainder_of_start_sequence.len();
let buffer_length = buf.len();
struct MaximalOccurance {
index: usize,
length: usize,
}
let maximal_start_sequence_occurance = (0..buffer_length)
.map(|i| {
let window = &&buf[buffer_length - i - 1
..usize::min(
buffer_length,
buffer_length - i - 1 + remainder_of_start_sequence.len(),
)];
let contained_length = contains(window, remainder_of_start_sequence);
if contained_length < remaining_start_sequence_bytes
&& i + 1 > contained_length
{
MaximalOccurance {
index: buffer_length - i - 1,
length: 0,
}
} else {
MaximalOccurance {
index: buffer_length - i - 1,
length: contained_length,
}
}
})
.max_by_key(|item| item.length)
.unwrap_or(MaximalOccurance {
index: 0,
length: 0,
});
if maximal_start_sequence_occurance.length == remaining_start_sequence_bytes {
*self = SMLMessageBuilder::Recording([].to_vec());
self.record(
&buf[maximal_start_sequence_occurance.index
+ maximal_start_sequence_occurance.length..]
.to_vec(),
);
} else if maximal_start_sequence_occurance.length > 0 {
*self = SMLMessageBuilder::IncompleteStartSignature(
maximal_start_sequence_occurance.length + start,
);
} else if maximal_start_sequence_occurance.length == 0 && buf.len() > 0 {
*self = SMLMessageBuilder::Empty;
};
}
SMLMessageBuilder::Recording(recorded) => {
recorded.append(&mut buf.to_vec());
let end = recorded
.windows(END_SEQUENCE_WITHOUT_CRC.len() + 3)
.enumerate()
.find(|(_, x)| x[..END_SEQUENCE_WITHOUT_CRC.len()] == *END_SEQUENCE_WITHOUT_CRC)
.map(|(index, _)| index);
if let Some(end) = end {
let (message, rest) = recorded.split_at_mut(end);
*self = SMLMessageBuilder::Complete {
data: message.to_vec(),
rest: rest[END_SEQUENCE_WITHOUT_CRC.len() + 3..].to_vec(),
}
}
}
_ => {}
}
}Trait Implementations§
source§impl Debug for SMLMessageBuilder
impl Debug for SMLMessageBuilder
source§impl PartialEq<SMLMessageBuilder> for SMLMessageBuilder
impl PartialEq<SMLMessageBuilder> for SMLMessageBuilder
source§fn eq(&self, other: &SMLMessageBuilder) -> bool
fn eq(&self, other: &SMLMessageBuilder) -> bool
This method tests for
self and other values to be equal, and is used
by ==.