1use core::error::Error as CoreError;
4
5use embedded_io_async::{Read, ReadExactError, Write};
6use zerocopy::{FromBytes, Immutable, IntoBytes};
7
8mod generated {
9 include!(concat!(env!("OUT_DIR"), "/client.rs"));
10}
11
12pub use generated::*;
13
14use crate::pdu::{CrcError, ValidationError};
15
16async fn write_frame<T, E>(mut dst: impl Write<Error = E>, frame: &T) -> Result<(), E>
17where
18 T: IntoBytes + Immutable,
19{
20 dst.write_all(frame.as_bytes()).await?;
21 dst.flush().await
22}
23
24async fn read_frame<T, E>(mut src: impl Read<Error = E>) -> Result<T, ReadExactError<E>>
25where
26 T: FromBytes + IntoBytes,
27{
28 let mut message = T::new_zeroed();
29 src.read_exact(message.as_mut_bytes()).await?;
30 Ok(message)
31}
32
33#[derive(Debug, thiserror_no_std::Error)]
35pub enum Error<Io: CoreError> {
36 #[error(transparent)]
38 Io(Io),
39 #[error("unexpected end of file")]
41 UnexpectedEof,
42 #[error(transparent)]
44 Crc(#[from] CrcError),
45 #[error("unexpected response from server")]
47 UnexpectedResponse,
48}
49
50impl<E: CoreError> From<ValidationError> for Error<E> {
51 fn from(e: ValidationError) -> Self {
52 match e {
53 ValidationError::Crc(crc) => Error::Crc(crc),
54 ValidationError::UnexpectedResponse => Error::UnexpectedResponse,
55 }
56 }
57}
58
59impl<E: CoreError> From<ReadExactError<E>> for Error<E> {
60 fn from(e: ReadExactError<E>) -> Self {
61 match e {
62 ReadExactError::Other(e) => Self::Io(e),
63 ReadExactError::UnexpectedEof => Self::UnexpectedEof,
64 }
65 }
66}