Skip to main content

psdk_fruit_emapi/
command.rs

1use crate::constants::{TYPE_ERROR, TYPE_PASSTHROUGH_ERROR, TYPE_RESPONSE};
2use crate::error::{EmapiError, Result};
3
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub struct EmapiCommand {
6  pub command_type: u8,
7  pub parent: u8,
8  pub child: u8,
9  pub payload: Vec<u8>,
10}
11
12impl EmapiCommand {
13  pub fn new(command_type: u8, parent: u8, child: u8, payload: impl Into<Vec<u8>>) -> Self {
14    Self {
15      command_type,
16      parent,
17      child,
18      payload: payload.into(),
19    }
20  }
21
22  pub fn try_new(
23    command_type: u16,
24    parent: u16,
25    child: u16,
26    payload: impl Into<Vec<u8>>,
27  ) -> Result<Self> {
28    Ok(Self::new(
29      check_byte(command_type, "type")?,
30      check_byte(parent, "parent")?,
31      check_byte(child, "child")?,
32      payload,
33    ))
34  }
35
36  pub fn is_ack_for(&self, parent: u8, child: u8) -> bool {
37    self.is_response_for(TYPE_RESPONSE, parent, child) && self.payload.is_empty()
38  }
39
40  pub fn is_response_for(&self, command_type: u8, parent: u8, child: u8) -> bool {
41    self.command_type == command_type && self.parent == parent && self.child == child
42  }
43
44  pub fn is_error(&self) -> bool {
45    self.command_type == TYPE_ERROR || self.command_type == TYPE_PASSTHROUGH_ERROR
46  }
47
48  pub fn is_protocol_error(&self) -> bool {
49    self.command_type == TYPE_ERROR
50  }
51
52  pub fn is_passthrough_error(&self) -> bool {
53    self.command_type == TYPE_PASSTHROUGH_ERROR
54  }
55}
56
57fn check_byte(value: u16, name: &'static str) -> Result<u8> {
58  if value > 0xFF {
59    return Err(EmapiError::Range {
60      name,
61      min: 0,
62      max: 0xFF,
63      value: u64::from(value),
64    });
65  }
66  Ok(value as u8)
67}