Struct flipdot_core::Frame [−][src]
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
impl<'a> Frame<'a>
[src]
pub fn new(address: Address, message_type: MsgType, data: Data<'a>) -> Self
[src]
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())?);
pub fn message_type(&self) -> MsgType
[src]
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"), }
pub fn address(&self) -> Address
[src]
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!"); }
pub fn data(&self) -> &Cow<'a, [u8]>
[src]
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!"); }
pub fn into_data(self) -> Data<'a>
[src]
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());
pub fn to_bytes(&self) -> Vec<u8>
[src]
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());
pub fn to_bytes_with_newline(&self) -> Vec<u8>
[src]
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());
pub fn from_bytes(bytes: &[u8]) -> Result<Self, FrameError>
[src]
Parses the Intel HEX wire format into a new Frame
.
Errors
Returns:
FrameError::InvalidFrame
if the data does not conform to the Intel HEX format.FrameError::FrameDataMismatch
if the actual number of data bytes does not match the specified amount.FrameError::BadChecksum
if the computed checksum on the data does not match the specified one.
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);
pub fn write<W: Write>(&self, writer: &mut W) -> Result<(), FrameError>
[src]
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)?;
pub fn read<R: Read>(reader: &mut R) -> Result<Self, FrameError>
[src]
Reads the next line (up to \n
) from the reader and converts the result
into a new Frame
.
Errors
Returns:
FrameError::Io
if the read fails.FrameError::InvalidFrame
if the data does not conform to the Intel HEX format.FrameError::FrameDataMismatch
if the actual number of data bytes does not match the specified amount.FrameError::BadChecksum
if the computed checksum on the data does not match the specified one.
Examples
let mut port = serial::open("COM3")?; let frame = Frame::read(&mut port)?;
Trait Implementations
impl<'a> Clone for Frame<'a>
[src]
impl<'a> Debug for Frame<'a>
[src]
impl Display for Frame<'_>
[src]
fn fmt(&self, f: &mut Formatter<'_>) -> Result
[src]
Formats the frame in a human-readable way.
Useful for viewing traffic on a bus. All numbers are in hex.
impl<'a> Eq for Frame<'a>
[src]
impl<'a> From<Frame<'a>> for Message<'a>
[src]
fn from(frame: Frame<'a>) -> Self
[src]
Converts a Frame
into a Message
.
This cannot fail as all valid Frame
s are representable as Message
s (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);
impl<'a> From<Message<'a>> for Frame<'a>
[src]
fn from(message: Message<'a>) -> Self
[src]
Converts a Message
into a Frame
.
This cannot fail as all Message
s can be represented as Frame
s.
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);
impl<'a> Hash for Frame<'a>
[src]
fn hash<__H: Hasher>(&self, state: &mut __H)
[src]
pub fn hash_slice<H>(data: &[Self], state: &mut H) where
H: Hasher,
1.3.0[src]
H: Hasher,
impl<'a> PartialEq<Frame<'a>> for Frame<'a>
[src]
impl<'a> StructuralEq for Frame<'a>
[src]
impl<'a> StructuralPartialEq for Frame<'a>
[src]
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
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
pub fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T> ToOwned for T where
T: Clone,
[src]
T: Clone,
type Owned = T
The resulting type after obtaining ownership.
pub fn to_owned(&self) -> T
[src]
pub fn clone_into(&self, target: &mut T)
[src]
impl<T> ToString for T where
T: Display + ?Sized,
[src]
T: Display + ?Sized,
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
pub fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,