1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 107 108
//! Traits used to pack/unpack structs and enums from EtherCAT packets on the wire.
//!
//! This crate is designed for use with [`ethercrab`](https://docs.rs/ethercrab) but can be
//! used standalone too.
//!
//! While these traits can be implemented by hand as normal, it is recommended to derive them using
//! [`ethercrab-wire-derive`](https://docs.rs/ethercrab-wire-derive) where possible.
//!
//! # Experimental
//!
//! This crate is in its early stages and may contain bugs or publish breaking changes at any time.
//! It is in use by [`ethercrab`](https://docs.rs/ethercrab) and is well exercised there,
//! but please use with caution in your own code.
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(missing_docs)]
#![deny(missing_copy_implementations)]
#![deny(trivial_casts)]
#![deny(trivial_numeric_casts)]
#![deny(unused_import_braces)]
#![deny(unused_qualifications)]
#![deny(rustdoc::broken_intra_doc_links)]
#![deny(rustdoc::private_intra_doc_links)]
mod error;
mod impls;
pub use error::WireError;
pub use ethercrab_wire_derive::{EtherCrabWireRead, EtherCrabWireReadWrite, EtherCrabWireWrite};
/// A type to be received from the wire, according to EtherCAT spec rules (packed bits, little
/// endian).
///
/// This trait is [derivable](https://docs.rs/ethercrab-wire-derive).
pub trait EtherCrabWireRead: Sized {
/// Unpack this type from the beginning of the given buffer.
fn unpack_from_slice(buf: &[u8]) -> Result<Self, WireError>;
}
/// A type to be sent/received on the wire, according to EtherCAT spec rules (packed bits, little
/// endian).
///
/// This trait is [derivable](https://docs.rs/ethercrab-wire-derive).
pub trait EtherCrabWireWrite {
/// Pack the type and write it into the beginning of `buf`.
///
/// The default implementation of this method will return an error if the buffer is not long
/// enough.
fn pack_to_slice<'buf>(&self, buf: &'buf mut [u8]) -> Result<&'buf [u8], WireError> {
if buf.len() < self.packed_len() {
return Err(WireError::WriteBufferTooShort {
expected: self.packed_len(),
got: buf.len(),
});
}
Ok(self.pack_to_slice_unchecked(buf))
}
/// Pack the type and write it into the beginning of `buf`.
///
/// # Panics
///
/// This method must panic if `buf` is too short to hold the packed data.
fn pack_to_slice_unchecked<'buf>(&self, buf: &'buf mut [u8]) -> &'buf [u8];
/// Get the length in bytes of this item when packed.
fn packed_len(&self) -> usize;
}
/// A type that can be both written to the wire and read back from it.
///
/// This trait is [derivable](https://docs.rs/ethercrab-wire-derive).
pub trait EtherCrabWireReadWrite: EtherCrabWireRead + EtherCrabWireWrite {}
impl<T> EtherCrabWireReadWrite for T where T: EtherCrabWireRead + EtherCrabWireWrite {}
/// Implemented for types with a known size at compile time.
///
/// This trait is implemented automatically if [`EtherCrabWireRead`], [`EtherCrabWireWrite`] or
/// [`EtherCrabWireReadWrite`] is [derived](https://docs.rs/ethercrab-wire-derive).
pub trait EtherCrabWireSized {
/// Packed size in bytes.
const PACKED_LEN: usize;
/// Used to define an array of the correct length. This type should be an array `[u8; N]` where
/// `N` is a fixed value or const generic as per the type this trait is implemented on.
type Buffer: AsRef<[u8]> + AsMut<[u8]>;
/// Create a buffer sized to contain the packed representation of this item.
fn buffer() -> Self::Buffer;
}
/// Implemented for writeable types with a known size at compile time.
///
/// This trait is implemented automatically if [`EtherCrabWireWrite`] or [`EtherCrabWireReadWrite`]
/// is [derived](https://docs.rs/ethercrab-wire-derive).
pub trait EtherCrabWireWriteSized: EtherCrabWireSized {
/// Pack this item to a fixed sized array.
fn pack(&self) -> Self::Buffer;
}
/// A readable type that has a size known at compile time.
///
/// This trait is [derivable](https://docs.rs/ethercrab-wire-derive).
pub trait EtherCrabWireReadSized: EtherCrabWireRead + EtherCrabWireSized {}
impl<T> EtherCrabWireReadSized for T where T: EtherCrabWireRead + EtherCrabWireSized {}