grid_sdk/protocol/location/
payload.rs1use protobuf::Message;
18use protobuf::RepeatedField;
19
20use std::error::Error as StdError;
21
22use super::errors::BuilderError;
23
24use crate::protocol::schema::state::PropertyValue;
25use crate::protos;
26use crate::protos::{location_payload, location_payload::LocationPayload_Action};
27use crate::protos::{
28 FromBytes, FromNative, FromProto, IntoBytes, IntoNative, IntoProto, ProtoConversionError,
29};
30
31#[derive(Copy, Clone, Debug, PartialEq)]
35pub enum LocationNamespace {
36 Gs1,
37}
38
39impl Default for LocationNamespace {
40 fn default() -> Self {
41 LocationNamespace::Gs1
42 }
43}
44
45impl FromProto<protos::location_payload::LocationNamespace> for LocationNamespace {
46 fn from_proto(
47 namespace: protos::location_payload::LocationNamespace,
48 ) -> Result<Self, ProtoConversionError> {
49 match namespace {
50 protos::location_payload::LocationNamespace::GS1 => Ok(LocationNamespace::Gs1),
51 protos::location_payload::LocationNamespace::UNSET_TYPE => {
52 Err(ProtoConversionError::InvalidTypeError(
53 "Cannot convert Location_LocationType with type UNSET_TYPE".to_string(),
54 ))
55 }
56 }
57 }
58}
59
60impl FromNative<LocationNamespace> for protos::location_payload::LocationNamespace {
61 fn from_native(namespace: LocationNamespace) -> Result<Self, ProtoConversionError> {
62 match namespace {
63 LocationNamespace::Gs1 => Ok(protos::location_payload::LocationNamespace::GS1),
64 }
65 }
66}
67
68impl IntoProto<protos::location_payload::LocationNamespace> for LocationNamespace {}
69impl IntoNative<LocationNamespace> for protos::location_payload::LocationNamespace {}
70
71#[derive(Debug, Clone, PartialEq)]
73pub enum Action {
74 LocationCreate(LocationCreateAction),
75 LocationUpdate(LocationUpdateAction),
76 LocationDelete(LocationDeleteAction),
77}
78
79#[derive(Debug, Clone, PartialEq)]
81pub struct LocationPayload {
82 action: Action,
83 timestamp: u64,
84}
85
86impl LocationPayload {
87 pub fn action(&self) -> &Action {
88 &self.action
89 }
90
91 pub fn timestamp(&self) -> &u64 {
92 &self.timestamp
93 }
94}
95
96impl FromProto<protos::location_payload::LocationPayload> for LocationPayload {
97 fn from_proto(
98 payload: protos::location_payload::LocationPayload,
99 ) -> Result<Self, ProtoConversionError> {
100 let action = match payload.get_action() {
101 LocationPayload_Action::LOCATION_CREATE => Action::LocationCreate(
102 LocationCreateAction::from_proto(payload.get_location_create().clone())?,
103 ),
104 LocationPayload_Action::LOCATION_UPDATE => Action::LocationUpdate(
105 LocationUpdateAction::from_proto(payload.get_location_update().clone())?,
106 ),
107 LocationPayload_Action::LOCATION_DELETE => Action::LocationDelete(
108 LocationDeleteAction::from_proto(payload.get_location_delete().clone())?,
109 ),
110 LocationPayload_Action::UNSET_ACTION => {
111 return Err(ProtoConversionError::InvalidTypeError(
112 "Cannot convert LocationPayload_Action with type unset".to_string(),
113 ));
114 }
115 };
116 Ok(LocationPayload {
117 action,
118 timestamp: payload.get_timestamp(),
119 })
120 }
121}
122
123impl FromNative<LocationPayload> for protos::location_payload::LocationPayload {
124 fn from_native(native: LocationPayload) -> Result<Self, ProtoConversionError> {
125 let mut proto = location_payload::LocationPayload::new();
126
127 proto.set_timestamp(*native.timestamp());
128
129 match native.action() {
130 Action::LocationCreate(payload) => {
131 proto.set_action(LocationPayload_Action::LOCATION_CREATE);
132 proto.set_location_create(payload.clone().into_proto()?);
133 }
134 Action::LocationUpdate(payload) => {
135 proto.set_action(LocationPayload_Action::LOCATION_UPDATE);
136 proto.set_location_update(payload.clone().into_proto()?);
137 }
138 Action::LocationDelete(payload) => {
139 proto.set_action(LocationPayload_Action::LOCATION_DELETE);
140 proto.set_location_delete(payload.clone().into_proto()?);
141 }
142 }
143
144 Ok(proto)
145 }
146}
147
148impl FromBytes<LocationPayload> for LocationPayload {
149 fn from_bytes(bytes: &[u8]) -> Result<LocationPayload, ProtoConversionError> {
150 let proto: location_payload::LocationPayload =
151 Message::parse_from_bytes(bytes).map_err(|_| {
152 ProtoConversionError::SerializationError(
153 "Unable to get LocationPayload from bytes".into(),
154 )
155 })?;
156 proto.into_native()
157 }
158}
159
160impl IntoBytes for LocationPayload {
161 fn into_bytes(self) -> Result<Vec<u8>, ProtoConversionError> {
162 let proto = self.into_proto()?;
163 let bytes = proto.write_to_bytes().map_err(|_| {
164 ProtoConversionError::SerializationError(
165 "Unable to get LocationPayload from bytes".into(),
166 )
167 })?;
168 Ok(bytes)
169 }
170}
171
172impl IntoProto<protos::location_payload::LocationPayload> for LocationPayload {}
173impl IntoNative<LocationPayload> for protos::location_payload::LocationPayload {}
174
175#[derive(Debug)]
178pub enum LocationPayloadBuildError {
179 MissingField(String),
180}
181
182impl StdError for LocationPayloadBuildError {
183 fn description(&self) -> &str {
184 match *self {
185 LocationPayloadBuildError::MissingField(ref msg) => msg,
186 }
187 }
188
189 fn cause(&self) -> Option<&dyn StdError> {
190 match *self {
191 LocationPayloadBuildError::MissingField(_) => None,
192 }
193 }
194}
195
196impl std::fmt::Display for LocationPayloadBuildError {
197 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
198 match *self {
199 LocationPayloadBuildError::MissingField(ref s) => write!(f, "missing field \"{}\"", s),
200 }
201 }
202}
203
204#[derive(Default, Clone)]
206pub struct LocationPayloadBuilder {
207 action: Option<Action>,
208 timestamp: Option<u64>,
209}
210
211impl LocationPayloadBuilder {
212 pub fn new() -> Self {
213 LocationPayloadBuilder::default()
214 }
215 pub fn with_action(mut self, action: Action) -> Self {
216 self.action = Some(action);
217 self
218 }
219 pub fn with_timestamp(mut self, value: u64) -> Self {
220 self.timestamp = Some(value);
221 self
222 }
223 pub fn build(self) -> Result<LocationPayload, BuilderError> {
224 let action = self
225 .action
226 .ok_or_else(|| BuilderError::MissingField("'action' field is required".into()))?;
227 let timestamp = self
228 .timestamp
229 .ok_or_else(|| BuilderError::MissingField("'timestamp' field is required".into()))?;
230 Ok(LocationPayload { action, timestamp })
231 }
232}
233
234#[derive(Debug, Default, Clone, PartialEq)]
236pub struct LocationCreateAction {
237 namespace: LocationNamespace,
238 location_id: String,
239 owner: String,
240 properties: Vec<PropertyValue>,
241}
242
243impl LocationCreateAction {
244 pub fn namespace(&self) -> &LocationNamespace {
245 &self.namespace
246 }
247
248 pub fn location_id(&self) -> &str {
249 &self.location_id
250 }
251
252 pub fn owner(&self) -> &str {
253 &self.owner
254 }
255
256 pub fn properties(&self) -> &[PropertyValue] {
257 &self.properties
258 }
259}
260
261impl FromProto<location_payload::LocationCreateAction> for LocationCreateAction {
262 fn from_proto(
263 proto: location_payload::LocationCreateAction,
264 ) -> Result<Self, ProtoConversionError> {
265 Ok(LocationCreateAction {
266 namespace: LocationNamespace::from_proto(proto.get_namespace())?,
267 location_id: proto.get_location_id().to_string(),
268 owner: proto.get_owner().to_string(),
269 properties: proto
270 .get_properties()
271 .iter()
272 .cloned()
273 .map(PropertyValue::from_proto)
274 .collect::<Result<Vec<PropertyValue>, ProtoConversionError>>()?,
275 })
276 }
277}
278
279impl FromNative<LocationCreateAction> for location_payload::LocationCreateAction {
280 fn from_native(native: LocationCreateAction) -> Result<Self, ProtoConversionError> {
281 let mut proto = protos::location_payload::LocationCreateAction::new();
282 proto.set_namespace((*native.namespace()).into_proto()?);
283 proto.set_location_id(native.location_id().to_string());
284 proto.set_owner(native.owner().to_string());
285 proto.set_properties(RepeatedField::from_vec(
286 native
287 .properties()
288 .iter()
289 .cloned()
290 .map(PropertyValue::into_proto)
291 .collect::<Result<Vec<protos::schema_state::PropertyValue>, ProtoConversionError>>(
292 )?,
293 ));
294 Ok(proto)
295 }
296}
297
298impl FromBytes<LocationCreateAction> for LocationCreateAction {
299 fn from_bytes(bytes: &[u8]) -> Result<LocationCreateAction, ProtoConversionError> {
300 let proto: protos::location_payload::LocationCreateAction =
301 Message::parse_from_bytes(bytes).map_err(|_| {
302 ProtoConversionError::SerializationError(
303 "Unable to get LocationCreateAction from bytes".to_string(),
304 )
305 })?;
306 proto.into_native()
307 }
308}
309
310impl IntoBytes for LocationCreateAction {
311 fn into_bytes(self) -> Result<Vec<u8>, ProtoConversionError> {
312 let proto = self.into_proto()?;
313 let bytes = proto.write_to_bytes().map_err(|_| {
314 ProtoConversionError::SerializationError(
315 "Unable to get bytes from LocationCreateAction".to_string(),
316 )
317 })?;
318 Ok(bytes)
319 }
320}
321
322impl IntoProto<protos::location_payload::LocationCreateAction> for LocationCreateAction {}
323impl IntoNative<LocationCreateAction> for protos::location_payload::LocationCreateAction {}
324
325#[derive(Default, Debug)]
327pub struct LocationCreateActionBuilder {
328 namespace: Option<LocationNamespace>,
329 location_id: Option<String>,
330 owner: Option<String>,
331 properties: Option<Vec<PropertyValue>>,
332}
333
334impl LocationCreateActionBuilder {
335 pub fn new() -> Self {
336 LocationCreateActionBuilder::default()
337 }
338 pub fn with_namespace(mut self, value: LocationNamespace) -> Self {
339 self.namespace = Some(value);
340 self
341 }
342 pub fn with_location_id(mut self, value: String) -> Self {
343 self.location_id = Some(value);
344 self
345 }
346 pub fn with_owner(mut self, value: String) -> Self {
347 self.owner = Some(value);
348 self
349 }
350 pub fn with_properties(mut self, value: Vec<PropertyValue>) -> Self {
351 self.properties = Some(value);
352 self
353 }
354 pub fn build(self) -> Result<LocationCreateAction, BuilderError> {
355 let namespace = self.namespace.ok_or_else(|| {
356 BuilderError::MissingField("'namespace' field is required".to_string())
357 })?;
358 let location_id = self
359 .location_id
360 .ok_or_else(|| BuilderError::MissingField("'location_id' field is required".into()))?;
361 let owner = self
362 .owner
363 .ok_or_else(|| BuilderError::MissingField("'owner' field is required".into()))?;
364 let properties = self
365 .properties
366 .ok_or_else(|| BuilderError::MissingField("'properties' field is required".into()))?;
367 Ok(LocationCreateAction {
368 namespace,
369 location_id,
370 owner,
371 properties,
372 })
373 }
374}
375
376#[derive(Debug, Default, Clone, PartialEq)]
378pub struct LocationUpdateAction {
379 namespace: LocationNamespace,
380 location_id: String,
381 properties: Vec<PropertyValue>,
382}
383
384impl LocationUpdateAction {
385 pub fn namespace(&self) -> &LocationNamespace {
386 &self.namespace
387 }
388
389 pub fn location_id(&self) -> &str {
390 &self.location_id
391 }
392
393 pub fn properties(&self) -> &[PropertyValue] {
394 &self.properties
395 }
396}
397
398impl FromProto<protos::location_payload::LocationUpdateAction> for LocationUpdateAction {
399 fn from_proto(
400 proto: protos::location_payload::LocationUpdateAction,
401 ) -> Result<Self, ProtoConversionError> {
402 Ok(LocationUpdateAction {
403 namespace: LocationNamespace::from_proto(proto.get_namespace())?,
404 location_id: proto.get_location_id().to_string(),
405 properties: proto
406 .get_properties()
407 .iter()
408 .cloned()
409 .map(PropertyValue::from_proto)
410 .collect::<Result<Vec<PropertyValue>, ProtoConversionError>>()?,
411 })
412 }
413}
414
415impl FromNative<LocationUpdateAction> for protos::location_payload::LocationUpdateAction {
416 fn from_native(native: LocationUpdateAction) -> Result<Self, ProtoConversionError> {
417 let mut proto = protos::location_payload::LocationUpdateAction::new();
418 proto.set_namespace((*native.namespace()).into_proto()?);
419 proto.set_location_id(native.location_id().to_string());
420 proto.set_properties(RepeatedField::from_vec(
421 native
422 .properties()
423 .iter()
424 .cloned()
425 .map(PropertyValue::into_proto)
426 .collect::<Result<Vec<protos::schema_state::PropertyValue>, ProtoConversionError>>(
427 )?,
428 ));
429
430 Ok(proto)
431 }
432}
433
434impl FromBytes<LocationUpdateAction> for LocationUpdateAction {
435 fn from_bytes(bytes: &[u8]) -> Result<LocationUpdateAction, ProtoConversionError> {
436 let proto: protos::location_payload::LocationUpdateAction =
437 Message::parse_from_bytes(bytes).map_err(|_| {
438 ProtoConversionError::SerializationError(
439 "Unable to get LocationUpdateAction from bytes".to_string(),
440 )
441 })?;
442 proto.into_native()
443 }
444}
445
446impl IntoBytes for LocationUpdateAction {
447 fn into_bytes(self) -> Result<Vec<u8>, ProtoConversionError> {
448 let proto = self.into_proto()?;
449 let bytes = proto.write_to_bytes().map_err(|_| {
450 ProtoConversionError::SerializationError(
451 "Unable to get bytes from LocationUpdateAction".to_string(),
452 )
453 })?;
454 Ok(bytes)
455 }
456}
457
458impl IntoProto<protos::location_payload::LocationUpdateAction> for LocationUpdateAction {}
459impl IntoNative<LocationUpdateAction> for protos::location_payload::LocationUpdateAction {}
460
461#[derive(Default, Clone)]
463pub struct LocationUpdateActionBuilder {
464 namespace: Option<LocationNamespace>,
465 location_id: Option<String>,
466 properties: Vec<PropertyValue>,
467}
468
469impl LocationUpdateActionBuilder {
470 pub fn new() -> Self {
471 LocationUpdateActionBuilder::default()
472 }
473
474 pub fn with_namespace(mut self, namespace: LocationNamespace) -> Self {
475 self.namespace = Some(namespace);
476 self
477 }
478
479 pub fn with_location_id(mut self, location_id: String) -> Self {
480 self.location_id = Some(location_id);
481 self
482 }
483
484 pub fn with_properties(mut self, properties: Vec<PropertyValue>) -> Self {
485 self.properties = properties;
486 self
487 }
488
489 pub fn build(self) -> Result<LocationUpdateAction, BuilderError> {
490 let namespace = self.namespace.ok_or_else(|| {
491 BuilderError::MissingField("'namespace' field is required".to_string())
492 })?;
493
494 let location_id = self.location_id.ok_or_else(|| {
495 BuilderError::MissingField("'location_id' field is required".to_string())
496 })?;
497
498 let properties = {
499 if !self.properties.is_empty() {
500 self.properties
501 } else {
502 return Err(BuilderError::MissingField(
503 "'properties' field is required".to_string(),
504 ));
505 }
506 };
507
508 Ok(LocationUpdateAction {
509 namespace,
510 location_id,
511 properties,
512 })
513 }
514}
515
516#[derive(Debug, Default, Clone, PartialEq)]
518pub struct LocationDeleteAction {
519 namespace: LocationNamespace,
520 location_id: String,
521}
522
523impl LocationDeleteAction {
525 pub fn namespace(&self) -> &LocationNamespace {
526 &self.namespace
527 }
528
529 pub fn location_id(&self) -> &str {
530 &self.location_id
531 }
532}
533
534impl FromProto<protos::location_payload::LocationDeleteAction> for LocationDeleteAction {
535 fn from_proto(
536 proto: protos::location_payload::LocationDeleteAction,
537 ) -> Result<Self, ProtoConversionError> {
538 Ok(LocationDeleteAction {
539 namespace: LocationNamespace::from_proto(proto.get_namespace())?,
540 location_id: proto.get_location_id().to_string(),
541 })
542 }
543}
544
545impl FromNative<LocationDeleteAction> for protos::location_payload::LocationDeleteAction {
546 fn from_native(native: LocationDeleteAction) -> Result<Self, ProtoConversionError> {
547 let mut proto = protos::location_payload::LocationDeleteAction::new();
548 proto.set_namespace((*native.namespace()).into_proto()?);
549 proto.set_location_id(native.location_id().to_string());
550 Ok(proto)
551 }
552}
553
554impl FromBytes<LocationDeleteAction> for LocationDeleteAction {
555 fn from_bytes(bytes: &[u8]) -> Result<LocationDeleteAction, ProtoConversionError> {
556 let proto: protos::location_payload::LocationDeleteAction =
557 Message::parse_from_bytes(bytes).map_err(|_| {
558 ProtoConversionError::SerializationError(
559 "Unable to get LocationDeleteAction from bytes".to_string(),
560 )
561 })?;
562 proto.into_native()
563 }
564}
565
566impl IntoBytes for LocationDeleteAction {
567 fn into_bytes(self) -> Result<Vec<u8>, ProtoConversionError> {
568 let proto = self.into_proto()?;
569 let bytes = proto.write_to_bytes().map_err(|_| {
570 ProtoConversionError::SerializationError(
571 "Unable to get bytes from LocationDeleteAction".to_string(),
572 )
573 })?;
574 Ok(bytes)
575 }
576}
577
578impl IntoProto<protos::location_payload::LocationDeleteAction> for LocationDeleteAction {}
579impl IntoNative<LocationDeleteAction> for protos::location_payload::LocationDeleteAction {}
580
581#[derive(Default, Clone)]
583pub struct LocationDeleteActionBuilder {
584 namespace: Option<LocationNamespace>,
585 location_id: Option<String>,
586}
587
588impl LocationDeleteActionBuilder {
589 pub fn new() -> Self {
590 LocationDeleteActionBuilder::default()
591 }
592
593 pub fn with_namespace(mut self, namespace: LocationNamespace) -> Self {
594 self.namespace = Some(namespace);
595 self
596 }
597
598 pub fn with_location_id(mut self, location_id: String) -> Self {
599 self.location_id = Some(location_id);
600 self
601 }
602
603 pub fn build(self) -> Result<LocationDeleteAction, BuilderError> {
604 let namespace = self.namespace.ok_or_else(|| {
605 BuilderError::MissingField("'namespace' field is required".to_string())
606 })?;
607
608 let location_id = self.location_id.ok_or_else(|| {
609 BuilderError::MissingField("'location_id' field is required".to_string())
610 })?;
611
612 Ok(LocationDeleteAction {
613 namespace,
614 location_id,
615 })
616 }
617}