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 {}