ethercrab_wire/
lib.rs

1//! Traits used to pack/unpack structs and enums from EtherCAT packets on the wire.
2//!
3//! This crate is designed for use with [`ethercrab`](https://docs.rs/ethercrab) but can be
4//! used standalone too.
5//!
6//! While these traits can be implemented by hand as normal, it is recommended to derive them using
7//! [`ethercrab-wire-derive`](https://docs.rs/ethercrab-wire-derive) where possible.
8//!
9//! # Experimental
10//!
11//! This crate is in its early stages and may contain bugs or publish breaking changes at any time.
12//! It is in use by [`ethercrab`](https://docs.rs/ethercrab) and is well exercised there,
13//! but please use with caution in your own code.
14
15#![cfg_attr(not(feature = "std"), no_std)]
16#![deny(missing_docs)]
17#![deny(missing_copy_implementations)]
18#![deny(trivial_casts)]
19#![deny(trivial_numeric_casts)]
20#![deny(unused_import_braces)]
21#![deny(unused_qualifications)]
22#![deny(rustdoc::broken_intra_doc_links)]
23#![deny(rustdoc::private_intra_doc_links)]
24
25mod error;
26mod impls;
27
28pub use error::WireError;
29pub use ethercrab_wire_derive::{EtherCrabWireRead, EtherCrabWireReadWrite, EtherCrabWireWrite};
30
31/// A type to be received from the wire, according to EtherCAT spec rules (packed bits, little
32/// endian).
33///
34/// This trait is [derivable](https://docs.rs/ethercrab-wire-derive).
35pub trait EtherCrabWireRead: Sized {
36    /// Unpack this type from the beginning of the given buffer.
37    fn unpack_from_slice(buf: &[u8]) -> Result<Self, WireError>;
38}
39
40/// A type to be sent/received on the wire, according to EtherCAT spec rules (packed bits, little
41/// endian).
42///
43/// This trait is [derivable](https://docs.rs/ethercrab-wire-derive).
44pub trait EtherCrabWireWrite {
45    /// Pack the type and write it into the beginning of `buf`.
46    ///
47    /// The default implementation of this method will return an error if the buffer is not long
48    /// enough.
49    fn pack_to_slice<'buf>(&self, buf: &'buf mut [u8]) -> Result<&'buf [u8], WireError> {
50        buf.get(0..self.packed_len())
51            .ok_or(WireError::WriteBufferTooShort)?;
52
53        Ok(self.pack_to_slice_unchecked(buf))
54    }
55
56    /// Pack the type and write it into the beginning of `buf`.
57    ///
58    /// # Panics
59    ///
60    /// This method must panic if `buf` is too short to hold the packed data.
61    fn pack_to_slice_unchecked<'buf>(&self, buf: &'buf mut [u8]) -> &'buf [u8];
62
63    /// Get the length in bytes of this item when packed.
64    fn packed_len(&self) -> usize;
65}
66
67/// A type that can be both written to the wire and read back from it.
68///
69/// This trait is [derivable](https://docs.rs/ethercrab-wire-derive).
70pub trait EtherCrabWireReadWrite: EtherCrabWireRead + EtherCrabWireWrite {}
71
72impl<T> EtherCrabWireReadWrite for T where T: EtherCrabWireRead + EtherCrabWireWrite {}
73
74/// Implemented for types with a known size at compile time.
75///
76/// This trait is implemented automatically if [`EtherCrabWireRead`], [`EtherCrabWireWrite`] or
77/// [`EtherCrabWireReadWrite`] is [derived](https://docs.rs/ethercrab-wire-derive).
78pub trait EtherCrabWireSized {
79    /// Packed size in bytes.
80    const PACKED_LEN: usize;
81
82    /// Used to define an array of the correct length. This type should be an array `[u8; N]` where
83    /// `N` is a fixed value or const generic as per the type this trait is implemented on.
84    type Buffer: AsRef<[u8]> + AsMut<[u8]>;
85
86    /// Create a buffer sized to contain the packed representation of this item.
87    fn buffer() -> Self::Buffer;
88}
89
90/// Implemented for writeable types with a known size at compile time.
91///
92/// This trait is implemented automatically if [`EtherCrabWireWrite`] or [`EtherCrabWireReadWrite`]
93/// is [derived](https://docs.rs/ethercrab-wire-derive).
94pub trait EtherCrabWireWriteSized: EtherCrabWireSized {
95    /// Pack this item to a fixed sized array.
96    fn pack(&self) -> Self::Buffer;
97}
98
99/// A readable type that has a size known at compile time.
100///
101/// This trait is [derivable](https://docs.rs/ethercrab-wire-derive).
102pub trait EtherCrabWireReadSized: EtherCrabWireRead + EtherCrabWireSized {}
103
104impl<T> EtherCrabWireReadSized for T where T: EtherCrabWireRead + EtherCrabWireSized {}