1use std::collections::HashSet;
2use std::convert::Infallible;
3use std::iter::FromIterator;
4use std::string::FromUtf8Error;
5
6use serde::{Deserialize, Serialize};
7use uuid::Uuid;
8
9
10use crate::{ResourceAddress, ResourceCreate, ResourceIdentifier, ResourceKey, ResourceKind, ResourceSelector, ResourceStub, ResourceType, SkewerCase, Specific, ResourceId, Resource};
11use crate::error::Error;
12use crate::data::{DataSet, BinSrc, Meta};
13use crate::property::{ResourcePropertyValueSelector, ResourceValueSelector};
14
15pub struct ProtoMessage<P> {
16 pub id: MessageId,
17 pub from: Option<MessageFrom>,
18 pub to: Option<MessageTo>,
19 pub payload: Option<P>,
20 pub trace: bool,
21 pub log: bool,
22}
23
24impl<P> ProtoMessage<P> {
25 pub fn new() -> Self {
26 ProtoMessage {
27 id: MessageId::new_v4(),
28 from: Option::None,
29 to: Option::None,
30 payload: None,
31 trace: false,
32 log: false,
33 }
34 }
35
36 pub fn validate(&self) -> Result<(), Error> {
37 if self.to.is_none() {
38 Err("ProtoMessage: RESOURCE to must be set".into())
39 } else if self.from.is_none() {
40 Err("ProtoMessage: from must be set".into())
41 } else if let Option::None = self.payload {
42 Err("ProtoMessage: message payload cannot be None".into())
43 } else {
44 Ok(())
45 }
46 }
47
48 pub fn create(self) -> Result<Message<P>, Error> {
49 if let &Option::None = &self.payload {
50 return Err("ResourceMessagePayload cannot be None".into());
51 }
52
53 Ok(Message {
54 id: self.id,
55 from: self.from.ok_or("need to set 'from' in ProtoMessage")?,
56 to: self.to.ok_or("need to set 'to' in ProtoMessage")?,
57 payload: self
58 .payload
59 .ok_or("need to set a payload in ProtoMessage")?,
60 trace: self.trace,
61 log: self.log,
62 })
63 }
64
65 pub fn to(&mut self, to: MessageTo) {
66 self.to = Option::Some(to);
67 }
68
69 pub fn from(&mut self, from: MessageFrom) {
70 self.from = Option::Some(from);
71 }
72
73 pub fn payload(&mut self, payload: P) {
74 self.payload = Option::Some(payload);
75 }
76}
77
78
79
80pub struct ProtoMessageReply<P> {
81 pub id: MessageId,
82 pub from: Option<MessageFrom>,
83 pub payload: Option<P>,
84 pub reply_to: Option<MessageId>,
85 pub trace: bool,
86 pub log: bool,
87}
88
89impl<P> ProtoMessageReply<P> {
90 pub fn new() -> Self {
91 ProtoMessageReply {
92 id: MessageId::new_v4(),
93 from: Option::None,
94 payload: None,
95 reply_to: Option::None,
96 trace: false,
97 log: false,
98 }
99 }
100
101 pub fn validate(&self) -> Result<(), Error> {
102 if self.reply_to.is_none() {
103 Err("ProtoMessageReply:reply_to must be set".into())
104 } else if self.from.is_none() {
105 Err("ProtoMessageReply: from must be set".into())
106 } else if let Option::None = self.payload {
107 Err("ProtoMessageReply: message payload cannot be None".into())
108 } else {
109 Ok(())
110 }
111 }
112
113 pub fn create(self) -> Result<MessageReply<P>, Error> {
114 if let &Option::None = &self.payload {
115 return Err("ResourceMessagePayload cannot be None".into());
116 }
117
118
119 Ok(MessageReply {
120 id: self.id,
121 from: self.from.ok_or("need to set 'from' in ProtoMessageReply")?,
122 reply_to: self
123 .reply_to
124 .ok_or("need to set 'reply_to' in ProtoMessageReply")?,
125 payload: self
126 .payload
127 .ok_or("need to set a payload in ProtoMessageReply")?,
128 trace: self.trace,
129 log: self.log,
130 })
131 }
132
133 pub fn from(&mut self, from: MessageFrom) {
134 self.from = Option::Some(from);
135 }
136
137 pub fn payload(&mut self, payload: P) {
138 self.payload = Option::Some(payload);
139 }
140}
141
142#[derive(Clone, Serialize, Deserialize)]
143pub struct Message<P> {
144 pub id: MessageId,
145 pub from: MessageFrom,
146 pub to: MessageTo,
147 pub payload: P,
148 pub trace: bool,
149 pub log: bool,
150}
151
152#[derive(Clone, Serialize, Deserialize)]
153pub struct MessageReply<P> {
154 pub id: MessageId,
155 pub from: MessageFrom,
156 pub reply_to: MessageId,
157 pub payload: P,
158 pub trace: bool,
159 pub log: bool,
160}
161
162impl<P> Message<P> {
163
164}
165
166
167
168
169
170
171pub type MessageTo = ResourceIdentifier;
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
174pub enum MessageFrom {
175 Inject,
176 Resource(ResourceIdentifier),
177}
178
179#[derive(Clone, Serialize, Deserialize)]
180pub enum ResourceRequestMessage {
181 Create(ResourceCreate),
182 Select(ResourceSelector),
183 Unique(ResourceType),
184 SelectValues(ResourcePropertyValueSelector),
185 UpdateState(DataSet<BinSrc>)
186}
187
188#[derive(Clone, Serialize, Deserialize)]
189pub enum ResourceResponseMessage {
190 Resource(Option<ResourceStub>),
191 Resources(Vec<ResourceStub>),
192 Unique(ResourceId),
193 State(DataSet<BinSrc>),
194 Fail(Fail),
195}
196
197#[derive(Clone, Serialize, Deserialize)]
198pub struct ResourcePortMessage{
199 pub port: String,
200 pub payload: DataSet<BinSrc>
201}
202
203#[derive(Clone, Serialize, Deserialize)]
204pub struct ResourcePortReply{
205 pub payload: DataSet<BinSrc>
206}
207
208pub type Raw = Vec<u8>;
209pub type RawPayload = Vec<u8>;
210pub type RawState = Vec<u8>;
211
212pub enum PortIdentifier{
213 Key(PortKey),
214 Address(PortAddress)
215}
216
217
218pub type PortIndex = u16;
219
220#[derive(Clone,Serialize,Deserialize,Hash,Eq,PartialEq)]
221pub struct PortKey {
222 pub resource: ResourceIdentifier,
223 pub port: PortIndex
224}
225
226#[derive(Clone,Serialize,Deserialize,Hash,Eq,PartialEq)]
227pub struct PortAddress{
228 pub resource: ResourceIdentifier,
229 pub port: SkewerCase
230}
231
232pub type MessageId = Uuid;
233
234#[derive(Debug, Clone, Serialize, Deserialize)]
235pub enum Fail {
236 Error(String),
237Unexpected {
239 expected: String,
240 received: String,
241 },
242 DoNotKnowSpecific(Specific),
243 ResourceStateFinal(ResourceIdentifier),
244 ResourceAddressAlreadyInUse(ResourceAddress),
245 ResourceNotFound(ResourceIdentifier),
246 WrongResourceType {
247 expected: HashSet<ResourceType>,
248 received: ResourceType,
249 },
250 WrongParentResourceType {
251 expected: HashSet<ResourceType>,
252 received: Option<ResourceType>,
253 },
254 ResourceTypeRequiresOwner,
255 ChannelRecvErr,
256 CannotSelectResourceHost,
257 ResourceCannotGenerateAddress,
258 SuitableHostNotAvailable(String),
259 SqlError(String),
260 CannotCreateNothingResourceTypeItIsThereAsAPlaceholderDummy,
261 ResourceTypeMismatch(String),
262 Timeout,
263 InvalidResourceState(String),
264 NoProvisioner(ResourceKind),
265 QueueOverflow,
266}
267
268impl Fail {
269 pub fn trace(fail: Fail) -> Self {
270 eprintln!("{}", fail.to_string().as_str());
271 fail
272 }
273
274 pub fn expected(expected: &str) -> Self {
275 eprintln!("{}",expected);
276 Self::Unexpected {
277 expected: expected.to_string(),
278 received: "_".to_string(),
279 }
280 }
281
282 pub fn unexpected<T: ToString>(expected: &str, received: T) -> Self {
283 eprintln!("expected: {}, received: {}", expected, received.to_string());
284 Self::Unexpected {
285 expected: expected.to_string(),
286 received: received.to_string(),
287 }
288 }
289}
290
291impl ToString for Fail {
292 fn to_string(&self) -> String {
293 match self {
294 Fail::Timeout => "Timeout".to_string(),
295 Fail::Error(message) => format!("Error({})", message),
296 Fail::Unexpected { expected, received } => format!(
297 "Unexpected( expected: {}, received: {} )",
298 expected, received
299 )
300 .to_string(),
301 Fail::DoNotKnowSpecific(_) => "DoNotKnowSpecific".to_string(),
302 Fail::ResourceNotFound(id) => {
303 format!("ResourceNotFound({})", id.to_string()).to_string()
304 }
305 Fail::WrongResourceType { expected, received } => format!(
306 "WrongResourceType(expected:[_],received:{})",
307 received.to_string()
308 ),
309 Fail::ChannelRecvErr => "ChannelRecvErr".to_string(),
310 Fail::ResourceTypeRequiresOwner => "ResourceTypeRequiresOwner".to_string(),
311 Fail::CannotSelectResourceHost => "CannotSelectResourceHost".to_string(),
312 Fail::WrongParentResourceType { expected, received } => format!(
313 "WrongParentResourceType(expected:[_],received:{})",
314 match received {
315 None => "None".to_string(),
316 Some(expected) => expected.to_string(),
317 }
318 ),
319 Fail::ResourceCannotGenerateAddress => "ResourceCannotGenerateAddress".to_string(),
320 Fail::SuitableHostNotAvailable(detail) => {
321 format!("SuitableHostNotAvailable({})", detail.to_string())
322 }
323 Fail::SqlError(detail) => format!("SqlError({})", detail.to_string()),
324 Fail::CannotCreateNothingResourceTypeItIsThereAsAPlaceholderDummy => {
325 "CannotCreateNothingResourceTypeItIsThereAsAPlaceholderDummy".to_string()
326 }
327 Fail::ResourceTypeMismatch(detail) => {
328 format!("ResourceTypeMismatch({})", detail.to_string()).to_string()
329 }
330 Fail::ResourceStateFinal(_) => "ResourceStateFinal".to_string(),
331 Fail::ResourceAddressAlreadyInUse(_) => "ResourceAddressAlreadyInUse".to_string(),
332 Fail::InvalidResourceState(message) => {
333 format!("InvalidResourceState({})", message).to_string()
334 }
335 Fail::NoProvisioner(kind) => format!("NoProvisioner({})", kind.to_string()).to_string(),
336 Fail::QueueOverflow => "QueueOverflow".to_string(),
337 }
338 }
339}
340
341
342
343impl From<FromUtf8Error> for Fail {
344 fn from(e: FromUtf8Error) -> Self {
345 Fail::Error(e.to_string())
346 }
347}
348
349impl From<crate::error::Error> for Fail {
350 fn from(e: crate::error::Error) -> Self {
351 Fail::Error(e.to_string())
352 }
353}
354
355
356impl From<Infallible> for Fail {
357 fn from(e: Infallible) -> Self {
358 Fail::Error(format!("{}", e.to_string()))
359 }
360}
361