enet_proto/
req.rs

1mod value;
2
3use crate::ProtocolVersion;
4use derive_more::{Constructor, From, IsVariant, TryInto};
5use enum_kinds::EnumKind;
6use serde::Serialize;
7use std::{convert::TryFrom, time::SystemTime};
8
9pub use value::*;
10
11mod sealed {
12  pub trait Sealed {}
13}
14
15pub trait RequestType: Into<Request> + TryFrom<Request> + sealed::Sealed {
16  fn protocol_version(&self) -> ProtocolVersion;
17}
18
19macro_rules! impl_request_type {
20  ($t:ty => $e:expr) => {
21    impl sealed::Sealed for $t {}
22    impl RequestType for $t {
23      #[inline]
24      fn protocol_version(&self) -> ProtocolVersion {
25        $e
26      }
27    }
28  };
29}
30
31#[derive(Serialize, Debug, Constructor, Clone)]
32#[serde(rename_all = "UPPERCASE")]
33pub struct VersionReq;
34impl_request_type!(VersionReq => ProtocolVersion::ZeroZeroThree);
35
36#[derive(Serialize, Debug, Constructor, Clone)]
37#[serde(rename_all = "UPPERCASE")]
38pub struct GetChannelInfoAllReq;
39impl_request_type!(GetChannelInfoAllReq => ProtocolVersion::ZeroZeroThree);
40
41#[derive(Serialize, Debug, Constructor, Clone)]
42#[serde(rename_all = "UPPERCASE")]
43pub struct ItemValueSignInReq {
44  pub items: Vec<u32>,
45}
46impl_request_type!(ItemValueSignInReq => ProtocolVersion::ZeroZeroThree);
47
48#[derive(Serialize, Debug, Constructor, Clone)]
49#[serde(rename_all = "UPPERCASE")]
50pub struct ItemValueSignOutReq {
51  pub items: Vec<u32>,
52}
53impl_request_type!(ItemValueSignOutReq => ProtocolVersion::ZeroZeroThree);
54
55#[derive(Serialize, Debug, Constructor, Clone)]
56#[serde(rename_all = "UPPERCASE")]
57pub struct BlockListReq {
58  #[serde(rename = "LIST-RANGE")]
59  pub list_range: u32,
60}
61impl_request_type!(BlockListReq => ProtocolVersion::ZeroZeroThree);
62
63#[derive(Serialize, Debug, Constructor, Clone)]
64#[serde(rename_all = "UPPERCASE")]
65pub struct ProjectListReq;
66impl_request_type!(ProjectListReq => ProtocolVersion::ZeroZeroThree);
67
68#[derive(Serialize, Debug, Constructor, Clone)]
69#[serde(rename_all = "UPPERCASE")]
70pub struct ItemValueSetReq {
71  pub values: Vec<ItemSetValue>,
72}
73impl_request_type!(ItemValueSetReq => ProtocolVersion::ZeroZeroThree);
74
75#[derive(Debug, Serialize, From, IsVariant, TryInto, EnumKind, Clone)]
76#[enum_kind(RequestKind)]
77#[serde(tag = "CMD")]
78pub enum Request {
79  #[serde(rename = "VERSION_REQ")]
80  Version(VersionReq),
81
82  #[serde(rename = "GET_CHANNEL_INFO_ALL_REQ")]
83  GetChannelInfoAll(GetChannelInfoAllReq),
84
85  #[serde(rename = "ITEM_VALUE_SIGN_IN_REQ")]
86  ItemValueSignIn(ItemValueSignInReq),
87
88  #[serde(rename = "ITEM_VALUE_SIGN_OUT_REQ")]
89  ItemValueSignOut(ItemValueSignOutReq),
90
91  #[serde(rename = "BLOCK_LIST_REQ")]
92  BlockList(BlockListReq),
93
94  #[serde(rename = "PROJECT_LIST_GET")]
95  ProjectList(ProjectListReq),
96
97  #[serde(rename = "ITEM_VALUE_SET")]
98  ItemValueSet(ItemValueSetReq),
99}
100
101impl Request {
102  #[inline]
103  pub fn kind(&self) -> RequestKind {
104    RequestKind::from(self)
105  }
106}
107
108impl sealed::Sealed for Request {}
109impl RequestType for Request {
110  fn protocol_version(&self) -> ProtocolVersion {
111    match self {
112      Request::Version(v) => v.protocol_version(),
113      Request::GetChannelInfoAll(v) => v.protocol_version(),
114      Request::ItemValueSignIn(v) => v.protocol_version(),
115      Request::ItemValueSignOut(v) => v.protocol_version(),
116      Request::BlockList(v) => v.protocol_version(),
117      Request::ProjectList(v) => v.protocol_version(),
118      Request::ItemValueSet(v) => v.protocol_version(),
119    }
120  }
121}
122
123#[derive(Debug, Serialize)]
124#[serde(rename_all = "UPPERCASE")]
125pub struct RequestEnvelope {
126  #[serde(flatten)]
127  pub body: Request,
128  pub protocol: ProtocolVersion,
129  #[serde(serialize_with = "serialize_enet_timestamp")]
130  pub timestamp: SystemTime,
131}
132
133impl RequestEnvelope {
134  pub fn new(request: impl RequestType) -> Self {
135    let protocol = request.protocol_version();
136    Self::_new(request.into(), protocol)
137  }
138
139  #[inline(never)]
140  fn _new(request: Request, protocol: ProtocolVersion) -> Self {
141    Self {
142      body: request,
143      protocol,
144      timestamp: SystemTime::now(),
145    }
146  }
147}
148
149fn serialize_enet_timestamp<S>(value: &SystemTime, serializer: S) -> Result<S::Ok, S::Error>
150where
151  S: serde::Serializer,
152{
153  let s = value
154    .duration_since(std::time::UNIX_EPOCH)
155    .unwrap()
156    .as_secs()
157    .to_string();
158
159  s.serialize(serializer)
160}