starlane_resources/
message.rs

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),
237/*    Reject(Reject),*/
238    Unexpected {
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