Struct Parser

Source
pub struct Parser { /* private fields */ }

Implementations§

Source§

impl Parser

Source

pub fn feed( &mut self, input: &[u8], ) -> Result<(usize, Option<UncheckedPacket>), Error>

Parse as much of input as possible into a packet. Returns the number of bytes read (the rest will need to be re-fed), and maybe a packet which will need handling.

assert_eq!(
    parser.feed(b"$hello#14").unwrap(),
    (9, Some(UncheckedPacket {
        kind: Kind::Packet,
        data: b"hello".to_vec(),
        checksum: *b"14",
    }))
);

Apart from splitting the input up and expanding the data, nothing else is done. No checksums are compared, no data is handled. This is just the most basic building block used to supply data that can be further validated and interpreted.

assert_eq!(
    parser.feed(b"$in:valid}]}}Hello* }]*!CHECKS#UM").unwrap(),
    (33, Some(UncheckedPacket {
        kind: Kind::Packet,
        data: b"in:valid}]Helloooo}}}}}CHECKS".to_vec(),
        checksum: *b"UM",
    }))
);

Note that although the GDB protocol mostly only uses 7 bits, this will not work without the 8th bit clear. This is to make the overhead of updating each element in the list optional. Although that’s simple: Every element’s 8th bit can be cleared so just do that before passing it to the parser.

assert_eq!(
    parser.feed(&[b'%', 1, 2, 99, 255, 128, 0, 200, b'#', 0, 0]).unwrap(),
    (11, Some(UncheckedPacket {
        kind: Kind::Notification,
        data: vec![1, 2, 99, 255, 128, 0, 200],
        checksum: [0, 0],
    }))
);

This is a state machine: You may input half a packet now and half in a later invocation.

let mut parser1 = Parser::default();
let (full_len, full_packet) = parser1.feed(full_input)?;

let mut parser2 = Parser::default();
let (start_input, end_input) = full_input.split_at(random_index);
let (start_len, start_packet) = parser2.feed(start_input)?;
let (end_len, end_packet) = parser2.feed(end_input)?;

assert_eq!(start_len + end_len, full_len, "The total consumed lengths must be equal");
assert_eq!(start_packet.or(end_packet), full_packet, "The end packets must be equal");

Trait Implementations§

Source§

impl Default for Parser

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl Freeze for Parser

§

impl RefUnwindSafe for Parser

§

impl Send for Parser

§

impl Sync for Parser

§

impl Unpin for Parser

§

impl UnwindSafe for Parser

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.