Struct flipdot_core::Frame

source ·
pub struct Frame<'a> { /* private fields */ }
Expand description

A low-level representation of an Intel HEX data frame.

The Luminator protocol uses the Intel HEX format but not its semantics. This struct handles parsing the raw bytes into a form we can reason about, dealing with checksums, and so forth. It makes no attempt to ascribe meaning to the address, message type, and data (that’s Message’s job).

Both owned and borrowed data are supported.

§Examples

use flipdot_core::{Address, Data, Frame, MsgType};

let frame = Frame::new(Address(2), MsgType(1), Data::try_new(vec![3, 31])?);
println!("Parsed frame is {}", frame);

let bytes = frame.to_bytes();
assert_eq!(b":02000201031FD9", bytes.as_slice());

let parsed = Frame::from_bytes(&bytes)?;
assert_eq!(parsed, frame);

§Format Details

The format consists of a leading colon, several numeric fields (two-character ASCII representations of hex bytes), and a final carriage return/linefeed terminator. Note that for convenience, Frame allows omitting the final CRLF sequence.

┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬ ┄ ┬────┬────┬────┬────┬────┬────┐
│ :  │ DataLen │      Address      │ MsgType │  Data 0 │...│  Data N │  Chksum │ \r │ \n │
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴ ┄ ┴────┴────┴────┴────┴────┴────┘
          └╌╌╌╌╌╌╌╌╌╌╌╌╌ # of ╌╌╌╌╌╌╌╌╌╌╌╌╌> ┆       Data bytes      ┆

The DataLen field describes how many two-character data byte sequences are present. Note that since it is represented as a single byte, the data length cannot exceed 255 (0xFF). If DataLen is 0, there are no data bytes, and MsgType is followed directly by Chksum. The checksum is a longitudinal redundancy check calculated on all numeric fields.

Implementations§

source§

impl<'a> Frame<'a>

source

pub fn new(address: Address, message_type: MsgType, data: Data<'a>) -> Self

Constructs a new Frame with the specified address, message type, and data.

§Examples
// some_data is moved into owning_frame.
let some_data = vec![1, 2, 3];
let owning_frame = Frame::new(Address(0xB), MsgType(0xA), Data::try_new(some_data)?);

// other_data is borrowed.
let other_data = vec![1, 2, 3];
let borrowing_frame = Frame::new(Address(0xD), MsgType(0xC), Data::try_new(other_data.as_slice())?);
source

pub fn message_type(&self) -> MsgType

Returns the message type of the frame.

§Examples
let frame = Frame::new(Address(1), MsgType(1), Data::try_new(vec![])?);
match frame.message_type() {
   MsgType(1) => println!("Message 1"),
   _ => println!("Something else"),
}
source

pub fn address(&self) -> Address

Returns the address of the frame.

§Examples
let frame = Frame::new(Address(1), MsgType(1), Data::try_new(vec![])?);
if frame.address() == Address(3) {
    println!("This frame is addressed to me!");
}
source

pub fn data(&self) -> &Cow<'a, [u8]>

Returns a reference to the frame’s data.

§Examples
let frame = Frame::new(Address(1), MsgType(1), Data::try_new(vec![10, 20])?);
if (frame.data().as_ref() == &[10, 20]) {
    println!("Found the expected data!");
}
source

pub fn into_data(self) -> Data<'a>

Consumes the frame and returns ownership of its data.

§Examples
let frame = Frame::new(Address(1), MsgType(1), Data::try_new(vec![6, 7])?);
let frame2 = Frame::new(Address(2), MsgType(2), frame.into_data());
source

pub fn to_bytes(&self) -> Vec<u8>

Converts the frame to its wire format, without trailing carriage return/linefeed.

§Examples
let frame = Frame::new(Address(2), MsgType(1), Data::try_new(vec![3, 31])?);
let bytes = frame.to_bytes();
assert_eq!(b":02000201031FD9", bytes.as_slice());
source

pub fn to_bytes_with_newline(&self) -> Vec<u8>

Converts the frame to its wire format, including trailing carriage return/linefeed.

§Examples
let frame = Frame::new(Address(2), MsgType(1), Data::try_new(vec![3, 31])?);
let bytes = frame.to_bytes_with_newline();
assert_eq!(b":02000201031FD9\r\n", bytes.as_slice());
source

pub fn from_bytes(bytes: &[u8]) -> Result<Self, FrameError>

Parses the Intel HEX wire format into a new Frame.

§Errors

Returns:

§Examples
let bytes = b":02000201031FD9\r\n";
let frame = Frame::from_bytes(&bytes[..])?;
assert_eq!(Frame::new(Address(2), MsgType(1), Data::try_new(vec![3, 31])?), frame);
source

pub fn write<W: Write>(&self, writer: &mut W) -> Result<(), FrameError>

Writes the byte representation (including CRLF) of the frame to a writer.

§Errors

Returns FrameError::Io if the write fails.

§Examples
let mut port = serial::open("COM3")?;
let frame = Frame::new(Address(2), MsgType(1), Data::try_new(vec![3, 31])?);
frame.write(&mut port)?;
source

pub fn read<R: Read>(reader: &mut R) -> Result<Self, FrameError>

Reads the next line (up to \n) from the reader and converts the result into a new Frame.

§Errors

Returns:

§Examples
let mut port = serial::open("COM3")?;
let frame = Frame::read(&mut port)?;

Trait Implementations§

source§

impl<'a> Clone for Frame<'a>

source§

fn clone(&self) -> Frame<'a>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<'a> Debug for Frame<'a>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Display for Frame<'_>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the frame in a human-readable way.

Useful for viewing traffic on a bus. All numbers are in hex.

source§

impl<'a> From<Frame<'a>> for Message<'a>

source§

fn from(frame: Frame<'a>) -> Self

Converts a Frame into a Message.

This cannot fail as all valid Frames are representable as Messages (though perhaps Unknown). The input Frame is consumed to allow efficiently reusing its data where possible.

§Examples
let frame = Frame::new(Address(0x12), MsgType(4), Data::try_new(vec![0x07])?);
let message = Message::from(frame);
assert_eq!(Message::ReportState(Address(0x12), State::ConfigReceived), message);
source§

impl<'a> From<Message<'a>> for Frame<'a>

source§

fn from(message: Message<'a>) -> Self

Converts a Message into a Frame.

This cannot fail as all Messages can be represented as Frames. The input Message is consumed to allow efficiently reusing its data where possible.

§Examples
let message = Message::ReportState(Address(0xFF), State::ConfigReceived);
let frame = Frame::from(message);
assert_eq!(Frame::new(Address(0xFF), MsgType(4), Data::try_new(vec![0x07])?), frame);
source§

impl<'a> Hash for Frame<'a>

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl<'a> PartialEq for Frame<'a>

source§

fn eq(&self, other: &Frame<'a>) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl<'a> Eq for Frame<'a>

source§

impl<'a> StructuralPartialEq for Frame<'a>

Auto Trait Implementations§

§

impl<'a> RefUnwindSafe for Frame<'a>

§

impl<'a> Send for Frame<'a>

§

impl<'a> Sync for Frame<'a>

§

impl<'a> Unpin for Frame<'a>

§

impl<'a> UnwindSafe for Frame<'a>

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> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T> ToString for T
where T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

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

§

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>,

§

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.