1use protobuf::Message;
18use protobuf::RepeatedField;
19
20use std::default::Default;
21
22use super::errors::BuilderError;
23use crate::protocol::{schema::state::PropertyValue, track_and_trace::state::Role};
24use crate::protos;
25use crate::protos::{
26 track_and_trace_payload, track_and_trace_payload::TrackAndTracePayload_Action,
27};
28use crate::protos::{
29 FromBytes, FromNative, FromProto, IntoBytes, IntoNative, IntoProto, ProtoConversionError,
30};
31
32#[derive(Debug, Clone, PartialEq)]
34pub struct CreateRecordAction {
35 record_id: String,
36 schema: String,
37 properties: Vec<PropertyValue>,
38}
39
40impl CreateRecordAction {
41 pub fn record_id(&self) -> &str {
42 &self.record_id
43 }
44 pub fn schema(&self) -> &str {
45 &self.schema
46 }
47 pub fn properties(&self) -> &[PropertyValue] {
48 &self.properties
49 }
50}
51
52#[derive(Default, Debug)]
54pub struct CreateRecordActionBuilder {
55 record_id: Option<String>,
56 schema: Option<String>,
57 properties: Option<Vec<PropertyValue>>,
58}
59
60impl CreateRecordActionBuilder {
61 pub fn new() -> Self {
62 CreateRecordActionBuilder::default()
63 }
64 pub fn with_record_id(mut self, value: String) -> Self {
65 self.record_id = Some(value);
66 self
67 }
68 pub fn with_schema(mut self, value: String) -> Self {
69 self.schema = Some(value);
70 self
71 }
72 pub fn with_properties(mut self, value: Vec<PropertyValue>) -> Self {
73 self.properties = Some(value);
74 self
75 }
76 pub fn build(self) -> Result<CreateRecordAction, BuilderError> {
77 let record_id = self
78 .record_id
79 .ok_or_else(|| BuilderError::MissingField("record_id".into()))?;
80 let schema = self
81 .schema
82 .ok_or_else(|| BuilderError::MissingField("schema".into()))?;
83 let properties = self
84 .properties
85 .ok_or_else(|| BuilderError::MissingField("properties".into()))?;
86 Ok(CreateRecordAction {
87 record_id,
88 schema,
89 properties,
90 })
91 }
92}
93
94impl FromProto<track_and_trace_payload::CreateRecordAction> for CreateRecordAction {
95 fn from_proto(
96 proto: track_and_trace_payload::CreateRecordAction,
97 ) -> Result<Self, ProtoConversionError> {
98 Ok(CreateRecordAction {
99 record_id: proto.get_record_id().to_string(),
100 schema: proto.get_schema().to_string(),
101 properties: proto
102 .get_properties()
103 .iter()
104 .cloned()
105 .map(PropertyValue::from_proto)
106 .collect::<Result<Vec<PropertyValue>, ProtoConversionError>>()?,
107 })
108 }
109}
110
111impl FromNative<CreateRecordAction> for track_and_trace_payload::CreateRecordAction {
112 fn from_native(create_record_action: CreateRecordAction) -> Result<Self, ProtoConversionError> {
113 let mut proto = track_and_trace_payload::CreateRecordAction::new();
114 proto.set_record_id(create_record_action.record_id().to_string());
115 proto.set_schema(create_record_action.schema().to_string());
116 proto.set_properties(RepeatedField::from_vec(
117 create_record_action
118 .properties()
119 .iter()
120 .cloned()
121 .map(PropertyValue::into_proto)
122 .collect::<Result<Vec<protos::schema_state::PropertyValue>, ProtoConversionError>>(
123 )?,
124 ));
125
126 Ok(proto)
127 }
128}
129
130impl FromBytes<CreateRecordAction> for CreateRecordAction {
131 fn from_bytes(bytes: &[u8]) -> Result<CreateRecordAction, ProtoConversionError> {
132 let proto: track_and_trace_payload::CreateRecordAction = Message::parse_from_bytes(bytes)
133 .map_err(|_| {
134 ProtoConversionError::SerializationError(
135 "Unable to get CreateRecordAction from bytes".into(),
136 )
137 })?;
138 proto.into_native()
139 }
140}
141impl IntoBytes for CreateRecordAction {
142 fn into_bytes(self) -> Result<Vec<u8>, ProtoConversionError> {
143 let proto = self.into_proto()?;
144 let bytes = proto.write_to_bytes().map_err(|_| {
145 ProtoConversionError::SerializationError(
146 "Unable to get CreateRecordAction from bytes".into(),
147 )
148 })?;
149 Ok(bytes)
150 }
151}
152impl IntoProto<track_and_trace_payload::CreateRecordAction> for CreateRecordAction {}
153impl IntoNative<CreateRecordAction> for track_and_trace_payload::CreateRecordAction {}
154
155#[derive(Debug, Clone, PartialEq)]
157pub struct FinalizeRecordAction {
158 record_id: String,
159}
160
161impl FinalizeRecordAction {
162 pub fn record_id(&self) -> &str {
163 &self.record_id
164 }
165}
166
167#[derive(Default, Debug)]
169pub struct FinalizeRecordActionBuilder {
170 record_id: Option<String>,
171}
172
173impl FinalizeRecordActionBuilder {
174 pub fn new() -> Self {
175 FinalizeRecordActionBuilder::default()
176 }
177 pub fn with_record_id(mut self, value: String) -> Self {
178 self.record_id = Some(value);
179 self
180 }
181 pub fn build(self) -> Result<FinalizeRecordAction, BuilderError> {
182 let record_id = self
183 .record_id
184 .ok_or_else(|| BuilderError::MissingField("record_id".into()))?;
185 Ok(FinalizeRecordAction { record_id })
186 }
187}
188
189impl FromProto<track_and_trace_payload::FinalizeRecordAction> for FinalizeRecordAction {
190 fn from_proto(
191 proto: track_and_trace_payload::FinalizeRecordAction,
192 ) -> Result<Self, ProtoConversionError> {
193 Ok(FinalizeRecordAction {
194 record_id: proto.get_record_id().to_string(),
195 })
196 }
197}
198
199impl FromNative<FinalizeRecordAction> for track_and_trace_payload::FinalizeRecordAction {
200 fn from_native(native: FinalizeRecordAction) -> Result<Self, ProtoConversionError> {
201 let mut proto = track_and_trace_payload::FinalizeRecordAction::new();
202 proto.set_record_id(native.record_id().to_string());
203 Ok(proto)
204 }
205}
206
207impl FromBytes<FinalizeRecordAction> for FinalizeRecordAction {
208 fn from_bytes(bytes: &[u8]) -> Result<FinalizeRecordAction, ProtoConversionError> {
209 let proto: track_and_trace_payload::FinalizeRecordAction = Message::parse_from_bytes(bytes)
210 .map_err(|_| {
211 ProtoConversionError::SerializationError(
212 "Unable to get CreateFinalizeAction from bytes".into(),
213 )
214 })?;
215 proto.into_native()
216 }
217}
218impl IntoBytes for FinalizeRecordAction {
219 fn into_bytes(self) -> Result<Vec<u8>, ProtoConversionError> {
220 let proto = self.into_proto()?;
221 let bytes = proto.write_to_bytes().map_err(|_| {
222 ProtoConversionError::SerializationError(
223 "Unable to get CreateFinalizeAction from bytes".into(),
224 )
225 })?;
226 Ok(bytes)
227 }
228}
229impl IntoProto<track_and_trace_payload::FinalizeRecordAction> for FinalizeRecordAction {}
230impl IntoNative<FinalizeRecordAction> for track_and_trace_payload::FinalizeRecordAction {}
231
232#[derive(Debug, Clone, PartialEq)]
234pub struct UpdatePropertiesAction {
235 record_id: String,
236 properties: Vec<PropertyValue>,
237}
238
239impl UpdatePropertiesAction {
240 pub fn record_id(&self) -> &str {
241 &self.record_id
242 }
243 pub fn properties(&self) -> &[PropertyValue] {
244 &self.properties
245 }
246}
247
248#[derive(Default, Debug)]
250pub struct UpdatePropertiesActionBuilder {
251 record_id: Option<String>,
252 properties: Option<Vec<PropertyValue>>,
253}
254
255impl UpdatePropertiesActionBuilder {
256 pub fn new() -> Self {
257 UpdatePropertiesActionBuilder::default()
258 }
259 pub fn with_record_id(mut self, value: String) -> Self {
260 self.record_id = Some(value);
261 self
262 }
263 pub fn with_properties(mut self, value: Vec<PropertyValue>) -> Self {
264 self.properties = Some(value);
265 self
266 }
267 pub fn build(self) -> Result<UpdatePropertiesAction, BuilderError> {
268 let record_id = self
269 .record_id
270 .ok_or_else(|| BuilderError::MissingField("record_id".into()))?;
271 let properties = self
272 .properties
273 .ok_or_else(|| BuilderError::MissingField("properties".into()))?;
274 Ok(UpdatePropertiesAction {
275 record_id,
276 properties,
277 })
278 }
279}
280
281impl FromProto<track_and_trace_payload::UpdatePropertiesAction> for UpdatePropertiesAction {
282 fn from_proto(
283 proto: track_and_trace_payload::UpdatePropertiesAction,
284 ) -> Result<Self, ProtoConversionError> {
285 Ok(UpdatePropertiesAction {
286 record_id: proto.get_record_id().to_string(),
287 properties: proto
288 .get_properties()
289 .iter()
290 .cloned()
291 .map(PropertyValue::from_proto)
292 .collect::<Result<Vec<PropertyValue>, ProtoConversionError>>()?,
293 })
294 }
295}
296
297impl FromNative<UpdatePropertiesAction> for track_and_trace_payload::UpdatePropertiesAction {
298 fn from_native(native: UpdatePropertiesAction) -> Result<Self, ProtoConversionError> {
299 let mut proto = track_and_trace_payload::UpdatePropertiesAction::new();
300 proto.set_record_id(native.record_id().to_string());
301 proto.set_properties(RepeatedField::from_vec(
302 native
303 .properties()
304 .iter()
305 .cloned()
306 .map(PropertyValue::into_proto)
307 .collect::<Result<Vec<protos::schema_state::PropertyValue>, ProtoConversionError>>(
308 )?,
309 ));
310 Ok(proto)
311 }
312}
313
314impl FromBytes<UpdatePropertiesAction> for UpdatePropertiesAction {
315 fn from_bytes(bytes: &[u8]) -> Result<UpdatePropertiesAction, ProtoConversionError> {
316 let proto: track_and_trace_payload::UpdatePropertiesAction =
317 Message::parse_from_bytes(bytes).map_err(|_| {
318 ProtoConversionError::SerializationError(
319 "Unable to get UpdatePropertiesAction from bytes".into(),
320 )
321 })?;
322 proto.into_native()
323 }
324}
325impl IntoBytes for UpdatePropertiesAction {
326 fn into_bytes(self) -> Result<Vec<u8>, ProtoConversionError> {
327 let proto = self.into_proto()?;
328 let bytes = proto.write_to_bytes().map_err(|_| {
329 ProtoConversionError::SerializationError(
330 "Unable to get UpdatePropertiesAction from bytes".into(),
331 )
332 })?;
333 Ok(bytes)
334 }
335}
336impl IntoProto<track_and_trace_payload::UpdatePropertiesAction> for UpdatePropertiesAction {}
337impl IntoNative<UpdatePropertiesAction> for track_and_trace_payload::UpdatePropertiesAction {}
338
339#[derive(Debug, Clone, PartialEq)]
341pub struct CreateProposalAction {
342 record_id: String,
343 receiving_agent: String,
344 role: Role,
345 properties: Vec<String>,
346 terms: String,
347}
348
349impl CreateProposalAction {
350 pub fn record_id(&self) -> &str {
351 &self.record_id
352 }
353 pub fn receiving_agent(&self) -> &str {
354 &self.receiving_agent
355 }
356 pub fn role(&self) -> &Role {
357 &self.role
358 }
359 pub fn properties(&self) -> &[String] {
360 &self.properties
361 }
362 pub fn terms(&self) -> &str {
363 &self.terms
364 }
365}
366
367#[derive(Default, Debug)]
369pub struct CreateProposalActionBuilder {
370 record_id: Option<String>,
371 receiving_agent: Option<String>,
372 role: Option<Role>,
373 properties: Option<Vec<String>>,
374 terms: Option<String>,
375}
376
377impl CreateProposalActionBuilder {
378 pub fn new() -> Self {
379 CreateProposalActionBuilder::default()
380 }
381 pub fn with_record_id(mut self, value: String) -> Self {
382 self.record_id = Some(value);
383 self
384 }
385 pub fn with_receiving_agent(mut self, value: String) -> Self {
386 self.receiving_agent = Some(value);
387 self
388 }
389 pub fn with_role(mut self, value: Role) -> Self {
390 self.role = Some(value);
391 self
392 }
393 pub fn with_properties(mut self, value: Vec<String>) -> Self {
394 self.properties = Some(value);
395 self
396 }
397 pub fn with_terms(mut self, value: String) -> Self {
398 self.terms = Some(value);
399 self
400 }
401 pub fn build(self) -> Result<CreateProposalAction, BuilderError> {
402 let record_id = self
403 .record_id
404 .ok_or_else(|| BuilderError::MissingField("record_id".into()))?;
405 let receiving_agent = self
406 .receiving_agent
407 .ok_or_else(|| BuilderError::MissingField("receiving_agent".into()))?;
408 let role = self
409 .role
410 .ok_or_else(|| BuilderError::MissingField("role".into()))?;
411 let properties = self
412 .properties
413 .ok_or_else(|| BuilderError::MissingField("properties".into()))?;
414 let terms = self
415 .terms
416 .ok_or_else(|| BuilderError::MissingField("terms".into()))?;
417 Ok(CreateProposalAction {
418 record_id,
419 receiving_agent,
420 role,
421 properties,
422 terms,
423 })
424 }
425}
426
427impl FromProto<track_and_trace_payload::CreateProposalAction> for CreateProposalAction {
428 fn from_proto(
429 proto: track_and_trace_payload::CreateProposalAction,
430 ) -> Result<Self, ProtoConversionError> {
431 Ok(CreateProposalAction {
432 record_id: proto.get_record_id().to_string(),
433 receiving_agent: proto.get_receiving_agent().to_string(),
434 role: Role::from_proto(proto.get_role())?,
435 properties: proto
436 .get_properties()
437 .iter()
438 .cloned()
439 .map(String::from)
440 .collect(),
441 terms: proto.get_terms().to_string(),
442 })
443 }
444}
445
446impl FromNative<CreateProposalAction> for track_and_trace_payload::CreateProposalAction {
447 fn from_native(native: CreateProposalAction) -> Result<Self, ProtoConversionError> {
448 let mut proto = track_and_trace_payload::CreateProposalAction::new();
449 proto.set_record_id(native.record_id().to_string());
450 proto.set_receiving_agent(native.receiving_agent().to_string());
451 proto.set_role(native.role().clone().into_proto()?);
452 proto.set_properties(RepeatedField::from_vec(native.properties().to_vec()));
453 proto.set_terms(native.terms().to_string());
454 Ok(proto)
455 }
456}
457
458impl FromBytes<CreateProposalAction> for CreateProposalAction {
459 fn from_bytes(bytes: &[u8]) -> Result<CreateProposalAction, ProtoConversionError> {
460 let proto: track_and_trace_payload::CreateProposalAction = Message::parse_from_bytes(bytes)
461 .map_err(|_| {
462 ProtoConversionError::SerializationError(
463 "Unable to get CreateProposalAction from bytes".into(),
464 )
465 })?;
466 proto.into_native()
467 }
468}
469impl IntoBytes for CreateProposalAction {
470 fn into_bytes(self) -> Result<Vec<u8>, ProtoConversionError> {
471 let proto = self.into_proto()?;
472 let bytes = proto.write_to_bytes().map_err(|_| {
473 ProtoConversionError::SerializationError(
474 "Unable to get CreateProposalAction from bytes".into(),
475 )
476 })?;
477 Ok(bytes)
478 }
479}
480impl IntoProto<track_and_trace_payload::CreateProposalAction> for CreateProposalAction {}
481impl IntoNative<CreateProposalAction> for track_and_trace_payload::CreateProposalAction {}
482
483#[derive(Debug, Clone, PartialEq)]
488pub enum Response {
489 Accept,
490 Reject,
491 Cancel,
492}
493
494impl Default for Response {
495 fn default() -> Response {
496 Response::Accept
497 }
498}
499
500impl FromProto<track_and_trace_payload::AnswerProposalAction_Response> for Response {
501 fn from_proto(
502 responses: track_and_trace_payload::AnswerProposalAction_Response,
503 ) -> Result<Self, ProtoConversionError> {
504 match responses {
505 track_and_trace_payload::AnswerProposalAction_Response::ACCEPT => Ok(Response::Accept),
506 track_and_trace_payload::AnswerProposalAction_Response::REJECT => Ok(Response::Reject),
507 track_and_trace_payload::AnswerProposalAction_Response::CANCEL => Ok(Response::Cancel),
508 }
509 }
510}
511
512impl FromNative<Response> for track_and_trace_payload::AnswerProposalAction_Response {
513 fn from_native(responses: Response) -> Result<Self, ProtoConversionError> {
514 match responses {
515 Response::Accept => Ok(track_and_trace_payload::AnswerProposalAction_Response::ACCEPT),
516 Response::Reject => Ok(track_and_trace_payload::AnswerProposalAction_Response::REJECT),
517 Response::Cancel => Ok(track_and_trace_payload::AnswerProposalAction_Response::CANCEL),
518 }
519 }
520}
521
522impl IntoProto<track_and_trace_payload::AnswerProposalAction_Response> for Response {}
523impl IntoNative<Response> for track_and_trace_payload::AnswerProposalAction_Response {}
524
525#[derive(Debug, Clone, PartialEq)]
527pub struct AnswerProposalAction {
528 record_id: String,
529 receiving_agent: String,
530 role: Role,
531 response: Response,
532}
533
534impl AnswerProposalAction {
535 pub fn record_id(&self) -> &str {
536 &self.record_id
537 }
538 pub fn receiving_agent(&self) -> &str {
539 &self.receiving_agent
540 }
541 pub fn role(&self) -> &Role {
542 &self.role
543 }
544 pub fn response(&self) -> &Response {
545 &self.response
546 }
547}
548
549#[derive(Default, Debug)]
551pub struct AnswerProposalActionBuilder {
552 record_id: Option<String>,
553 receiving_agent: Option<String>,
554 role: Option<Role>,
555 response: Option<Response>,
556}
557
558impl AnswerProposalActionBuilder {
559 pub fn new() -> Self {
560 AnswerProposalActionBuilder::default()
561 }
562 pub fn with_record_id(mut self, value: String) -> Self {
563 self.record_id = Some(value);
564 self
565 }
566 pub fn with_receiving_agent(mut self, value: String) -> Self {
567 self.receiving_agent = Some(value);
568 self
569 }
570 pub fn with_role(mut self, value: Role) -> Self {
571 self.role = Some(value);
572 self
573 }
574 pub fn with_response(mut self, value: Response) -> Self {
575 self.response = Some(value);
576 self
577 }
578 pub fn build(self) -> Result<AnswerProposalAction, BuilderError> {
579 let record_id = self
580 .record_id
581 .ok_or_else(|| BuilderError::MissingField("record_id".into()))?;
582 let receiving_agent = self
583 .receiving_agent
584 .ok_or_else(|| BuilderError::MissingField("receiving_agent".into()))?;
585 let role = self
586 .role
587 .ok_or_else(|| BuilderError::MissingField("role".into()))?;
588 let response = self
589 .response
590 .ok_or_else(|| BuilderError::MissingField("response".into()))?;
591 Ok(AnswerProposalAction {
592 record_id,
593 receiving_agent,
594 role,
595 response,
596 })
597 }
598}
599
600impl FromProto<track_and_trace_payload::AnswerProposalAction> for AnswerProposalAction {
601 fn from_proto(
602 proto: track_and_trace_payload::AnswerProposalAction,
603 ) -> Result<Self, ProtoConversionError> {
604 Ok(AnswerProposalAction {
605 record_id: proto.get_record_id().to_string(),
606 receiving_agent: proto.get_receiving_agent().to_string(),
607 role: Role::from_proto(proto.get_role())?,
608 response: Response::from_proto(proto.get_response())?,
609 })
610 }
611}
612
613impl FromNative<AnswerProposalAction> for track_and_trace_payload::AnswerProposalAction {
614 fn from_native(native: AnswerProposalAction) -> Result<Self, ProtoConversionError> {
615 let mut proto = track_and_trace_payload::AnswerProposalAction::new();
616 proto.set_record_id(native.record_id().to_string());
617 proto.set_receiving_agent(native.receiving_agent().to_string());
618 proto.set_role(native.role().clone().into_proto()?);
619 proto.set_response(native.response().clone().into_proto()?);
620
621 Ok(proto)
622 }
623}
624
625impl FromBytes<AnswerProposalAction> for AnswerProposalAction {
626 fn from_bytes(bytes: &[u8]) -> Result<AnswerProposalAction, ProtoConversionError> {
627 let proto: track_and_trace_payload::AnswerProposalAction = Message::parse_from_bytes(bytes)
628 .map_err(|_| {
629 ProtoConversionError::SerializationError(
630 "Unable to get AnswerProposalAction from bytes".into(),
631 )
632 })?;
633 proto.into_native()
634 }
635}
636impl IntoBytes for AnswerProposalAction {
637 fn into_bytes(self) -> Result<Vec<u8>, ProtoConversionError> {
638 let proto = self.into_proto()?;
639 let bytes = proto.write_to_bytes().map_err(|_| {
640 ProtoConversionError::SerializationError(
641 "Unable to get AnswerProposalAction from bytes".into(),
642 )
643 })?;
644 Ok(bytes)
645 }
646}
647impl IntoProto<track_and_trace_payload::AnswerProposalAction> for AnswerProposalAction {}
648impl IntoNative<AnswerProposalAction> for track_and_trace_payload::AnswerProposalAction {}
649
650#[derive(Debug, Clone, PartialEq)]
652pub struct RevokeReporterAction {
653 record_id: String,
654 reporter_id: String,
655 properties: Vec<String>,
656}
657
658impl RevokeReporterAction {
659 pub fn record_id(&self) -> &str {
660 &self.record_id
661 }
662 pub fn reporter_id(&self) -> &str {
663 &self.reporter_id
664 }
665 pub fn properties(&self) -> &[String] {
666 &self.properties
667 }
668}
669
670#[derive(Default, Debug)]
672pub struct RevokeReporterActionBuilder {
673 record_id: Option<String>,
674 reporter_id: Option<String>,
675 properties: Option<Vec<String>>,
676}
677
678impl RevokeReporterActionBuilder {
679 pub fn new() -> Self {
680 RevokeReporterActionBuilder::default()
681 }
682 pub fn with_record_id(mut self, value: String) -> Self {
683 self.record_id = Some(value);
684 self
685 }
686 pub fn with_reporter_id(mut self, value: String) -> Self {
687 self.reporter_id = Some(value);
688 self
689 }
690 pub fn with_properties(mut self, value: Vec<String>) -> Self {
691 self.properties = Some(value);
692 self
693 }
694 pub fn build(self) -> Result<RevokeReporterAction, BuilderError> {
695 let record_id = self
696 .record_id
697 .ok_or_else(|| BuilderError::MissingField("record_id".into()))?;
698 let reporter_id = self
699 .reporter_id
700 .ok_or_else(|| BuilderError::MissingField("reporter_id".into()))?;
701 let properties = self
702 .properties
703 .ok_or_else(|| BuilderError::MissingField("properties".into()))?;
704 Ok(RevokeReporterAction {
705 record_id,
706 reporter_id,
707 properties,
708 })
709 }
710}
711
712impl FromProto<track_and_trace_payload::RevokeReporterAction> for RevokeReporterAction {
713 fn from_proto(
714 proto: track_and_trace_payload::RevokeReporterAction,
715 ) -> Result<Self, ProtoConversionError> {
716 Ok(RevokeReporterAction {
717 record_id: proto.get_record_id().to_string(),
718 reporter_id: proto.get_reporter_id().to_string(),
719 properties: proto
720 .get_properties()
721 .iter()
722 .cloned()
723 .map(String::from)
724 .collect(),
725 })
726 }
727}
728
729impl FromNative<RevokeReporterAction> for track_and_trace_payload::RevokeReporterAction {
730 fn from_native(native: RevokeReporterAction) -> Result<Self, ProtoConversionError> {
731 let mut proto = track_and_trace_payload::RevokeReporterAction::new();
732 proto.set_record_id(native.record_id().to_string());
733 proto.set_reporter_id(native.reporter_id().to_string());
734 proto.set_properties(RepeatedField::from_vec(native.properties().to_vec()));
735
736 Ok(proto)
737 }
738}
739
740impl FromBytes<RevokeReporterAction> for RevokeReporterAction {
741 fn from_bytes(bytes: &[u8]) -> Result<RevokeReporterAction, ProtoConversionError> {
742 let proto: track_and_trace_payload::RevokeReporterAction = Message::parse_from_bytes(bytes)
743 .map_err(|_| {
744 ProtoConversionError::SerializationError(
745 "Unable to get RevokeReporterAction from bytes".into(),
746 )
747 })?;
748 proto.into_native()
749 }
750}
751impl IntoBytes for RevokeReporterAction {
752 fn into_bytes(self) -> Result<Vec<u8>, ProtoConversionError> {
753 let proto = self.into_proto()?;
754 let bytes = proto.write_to_bytes().map_err(|_| {
755 ProtoConversionError::SerializationError(
756 "Unable to get RevokeReporterAction from bytes".into(),
757 )
758 })?;
759 Ok(bytes)
760 }
761}
762impl IntoProto<track_and_trace_payload::RevokeReporterAction> for RevokeReporterAction {}
763impl IntoNative<RevokeReporterAction> for track_and_trace_payload::RevokeReporterAction {}
764
765#[derive(Debug, Clone, PartialEq)]
767pub enum Action {
768 CreateRecord(CreateRecordAction),
769 FinalizeRecord(FinalizeRecordAction),
770 UpdateProperties(UpdatePropertiesAction),
771 CreateProposal(CreateProposalAction),
772 AnswerProposal(AnswerProposalAction),
773 RevokeReporter(RevokeReporterAction),
774}
775
776#[derive(Debug, Clone, PartialEq)]
778pub struct TrackAndTracePayload {
779 action: Action,
780 timestamp: u64,
781}
782
783impl TrackAndTracePayload {
784 pub fn action(&self) -> &Action {
785 &self.action
786 }
787 pub fn timestamp(&self) -> &u64 {
788 &self.timestamp
789 }
790}
791
792#[derive(Default, Debug)]
794pub struct TrackAndTracePayloadBuilder {
795 action: Option<Action>,
796 timestamp: Option<u64>,
797}
798
799impl TrackAndTracePayloadBuilder {
800 pub fn new() -> Self {
801 TrackAndTracePayloadBuilder::default()
802 }
803 pub fn with_action(mut self, value: Action) -> Self {
804 self.action = Some(value);
805 self
806 }
807 pub fn with_timestamp(mut self, value: u64) -> Self {
808 self.timestamp = Some(value);
809 self
810 }
811 pub fn build(self) -> Result<TrackAndTracePayload, BuilderError> {
812 let action = self
813 .action
814 .ok_or_else(|| BuilderError::MissingField("action".into()))?;
815 let timestamp = self
816 .timestamp
817 .ok_or_else(|| BuilderError::MissingField("timestamp".into()))?;
818 Ok(TrackAndTracePayload { action, timestamp })
819 }
820}
821
822impl FromProto<track_and_trace_payload::TrackAndTracePayload> for TrackAndTracePayload {
823 fn from_proto(
824 proto: track_and_trace_payload::TrackAndTracePayload,
825 ) -> Result<Self, ProtoConversionError> {
826 let action = match proto.get_action() {
827 TrackAndTracePayload_Action::CREATE_RECORD => Action::CreateRecord(
828 CreateRecordAction::from_proto(proto.get_create_record().clone())?,
829 ),
830 TrackAndTracePayload_Action::FINALIZE_RECORD => Action::FinalizeRecord(
831 FinalizeRecordAction::from_proto(proto.get_finalize_record().clone())?,
832 ),
833 TrackAndTracePayload_Action::UPDATE_PROPERTIES => Action::UpdateProperties(
834 UpdatePropertiesAction::from_proto(proto.get_update_properties().clone())?,
835 ),
836 TrackAndTracePayload_Action::CREATE_PROPOSAL => Action::CreateProposal(
837 CreateProposalAction::from_proto(proto.get_create_proposal().clone())?,
838 ),
839 TrackAndTracePayload_Action::ANSWER_PROPOSAL => Action::AnswerProposal(
840 AnswerProposalAction::from_proto(proto.get_answer_proposal().clone())?,
841 ),
842 TrackAndTracePayload_Action::REVOKE_REPORTER => Action::RevokeReporter(
843 RevokeReporterAction::from_proto(proto.get_revoke_reporter().clone())?,
844 ),
845 TrackAndTracePayload_Action::UNSET_ACTION => {
846 return Err(ProtoConversionError::InvalidTypeError(
847 "Cannot convert TrackAndTracePayload_Action with type unset.".to_string(),
848 ));
849 }
850 };
851
852 Ok(TrackAndTracePayload {
853 action,
854 timestamp: proto.get_timestamp(),
855 })
856 }
857}
858
859impl FromNative<TrackAndTracePayload> for track_and_trace_payload::TrackAndTracePayload {
860 fn from_native(native: TrackAndTracePayload) -> Result<Self, ProtoConversionError> {
861 let mut proto = track_and_trace_payload::TrackAndTracePayload::new();
862
863 proto.set_timestamp(*native.timestamp());
864
865 match native.action() {
866 Action::CreateRecord(payload) => {
867 proto.set_action(TrackAndTracePayload_Action::CREATE_RECORD);
868 proto.set_create_record(payload.clone().into_proto()?);
869 }
870 Action::FinalizeRecord(payload) => {
871 proto.set_action(TrackAndTracePayload_Action::FINALIZE_RECORD);
872 proto.set_finalize_record(payload.clone().into_proto()?);
873 }
874 Action::UpdateProperties(payload) => {
875 proto.set_action(TrackAndTracePayload_Action::UPDATE_PROPERTIES);
876 proto.set_update_properties(payload.clone().into_proto()?);
877 }
878 Action::CreateProposal(payload) => {
879 proto.set_action(TrackAndTracePayload_Action::CREATE_PROPOSAL);
880 proto.set_create_proposal(payload.clone().into_proto()?);
881 }
882 Action::AnswerProposal(payload) => {
883 proto.set_action(TrackAndTracePayload_Action::ANSWER_PROPOSAL);
884 proto.set_answer_proposal(payload.clone().into_proto()?);
885 }
886 Action::RevokeReporter(payload) => {
887 proto.set_action(TrackAndTracePayload_Action::REVOKE_REPORTER);
888 proto.set_revoke_reporter(payload.clone().into_proto()?);
889 }
890 }
891
892 Ok(proto)
893 }
894}
895
896impl FromBytes<TrackAndTracePayload> for TrackAndTracePayload {
897 fn from_bytes(bytes: &[u8]) -> Result<TrackAndTracePayload, ProtoConversionError> {
898 let proto: track_and_trace_payload::TrackAndTracePayload = Message::parse_from_bytes(bytes)
899 .map_err(|_| {
900 ProtoConversionError::SerializationError(
901 "Unable to get TrackAndTracePaylaod from bytes".into(),
902 )
903 })?;
904 proto.into_native()
905 }
906}
907impl IntoBytes for TrackAndTracePayload {
908 fn into_bytes(self) -> Result<Vec<u8>, ProtoConversionError> {
909 let proto = self.into_proto()?;
910 let bytes = proto.write_to_bytes().map_err(|_| {
911 ProtoConversionError::SerializationError(
912 "Unable to get TrackAndTracePaylaod from bytes".into(),
913 )
914 })?;
915 Ok(bytes)
916 }
917}
918impl IntoProto<track_and_trace_payload::TrackAndTracePayload> for TrackAndTracePayload {}
919impl IntoNative<TrackAndTracePayload> for track_and_trace_payload::TrackAndTracePayload {}
920
921#[cfg(test)]
922mod tests {
923 use super::*;
924 use crate::protocol::schema::state::{DataType, PropertyValueBuilder};
925 use std::fmt::Debug;
926
927 fn test_from_bytes<T: FromBytes<T> + Clone + PartialEq + IntoBytes + Debug, F>(
928 under_test: T,
929 from_bytes: F,
930 ) where
931 F: Fn(&[u8]) -> Result<T, ProtoConversionError>,
932 {
933 let bytes = under_test.clone().into_bytes().unwrap();
934 let created_from_bytes = from_bytes(&bytes).unwrap();
935 assert_eq!(under_test, created_from_bytes);
936 }
937
938 #[test]
939 fn test_create_record_builder() {
941 let property_value = PropertyValueBuilder::new()
942 .with_name("egg".into())
943 .with_data_type(DataType::Number)
944 .with_number_value(42)
945 .build()
946 .unwrap();
947
948 let action = CreateRecordActionBuilder::new()
949 .with_record_id("32".into())
950 .with_schema("schema".into())
951 .with_properties(vec![property_value.clone()])
952 .build()
953 .unwrap();
954
955 assert_eq!(action.record_id(), "32");
956 assert_eq!(action.schema(), "schema");
957 assert!(action.properties().iter().any(|x| *x == property_value));
958 }
959
960 #[test]
961 fn test_create_record_bytes() {
964 let property_value = PropertyValueBuilder::new()
965 .with_name("egg".into())
966 .with_data_type(DataType::Number)
967 .with_number_value(42)
968 .build()
969 .unwrap();
970
971 let action = CreateRecordActionBuilder::new()
972 .with_record_id("32".into())
973 .with_schema("schema".into())
974 .with_properties(vec![property_value.clone()])
975 .build()
976 .unwrap();
977
978 test_from_bytes(action, CreateRecordAction::from_bytes);
979 }
980
981 #[test]
982 fn test_finalize_record_action_builder() {
984 let action = FinalizeRecordActionBuilder::new()
985 .with_record_id("32".into())
986 .build()
987 .unwrap();
988
989 assert_eq!(action.record_id(), "32");
990 }
991
992 #[test]
993 fn test_finalize_record_action_bytes() {
996 let action = FinalizeRecordActionBuilder::new()
997 .with_record_id("32".into())
998 .build()
999 .unwrap();
1000
1001 test_from_bytes(action, FinalizeRecordAction::from_bytes);
1002 }
1003
1004 #[test]
1005 fn test_update_properties_action() {
1007 let property_value = PropertyValueBuilder::new()
1008 .with_name("egg".into())
1009 .with_data_type(DataType::Number)
1010 .with_number_value(42)
1011 .build()
1012 .unwrap();
1013
1014 let action = UpdatePropertiesActionBuilder::new()
1015 .with_record_id("32".into())
1016 .with_properties(vec![property_value.clone()])
1017 .build()
1018 .unwrap();
1019
1020 assert_eq!(action.record_id(), "32");
1021 assert!(action.properties().iter().any(|x| *x == property_value));
1022 }
1023
1024 #[test]
1025 fn test_update_properties_action_bytes() {
1028 let property_value = PropertyValueBuilder::new()
1029 .with_name("egg".into())
1030 .with_data_type(DataType::Number)
1031 .with_number_value(42)
1032 .build()
1033 .unwrap();
1034
1035 let action = UpdatePropertiesActionBuilder::new()
1036 .with_record_id("32".into())
1037 .with_properties(vec![property_value.clone()])
1038 .build()
1039 .unwrap();
1040
1041 test_from_bytes(action, UpdatePropertiesAction::from_bytes);
1042 }
1043
1044 #[test]
1045 fn test_create_proposal_action_builder() {
1047 let action = CreateProposalActionBuilder::new()
1048 .with_record_id("32".into())
1049 .with_receiving_agent("jim".into())
1050 .with_role(Role::Custodian)
1051 .with_properties(vec!["egg".into()])
1052 .with_terms("term".to_string())
1053 .build()
1054 .unwrap();
1055
1056 assert_eq!(action.record_id(), "32");
1057 assert_eq!(action.receiving_agent(), "jim");
1058 assert_eq!(action.terms(), "term");
1059 assert_eq!(*action.role(), Role::Custodian);
1060 assert!(action.properties().iter().any(|x| x == "egg"));
1061 }
1062
1063 #[test]
1064 fn test_create_proposal_action_bytes() {
1067 let action = CreateProposalActionBuilder::new()
1068 .with_record_id("32".into())
1069 .with_receiving_agent("jim".into())
1070 .with_role(Role::Custodian)
1071 .with_properties(vec!["egg".into()])
1072 .with_terms("term".to_string())
1073 .build()
1074 .unwrap();
1075
1076 test_from_bytes(action, CreateProposalAction::from_bytes);
1077 }
1078
1079 #[test]
1080 fn test_answer_proposal_action_builder() {
1082 let action = AnswerProposalActionBuilder::new()
1083 .with_record_id("32".into())
1084 .with_receiving_agent("jim".into())
1085 .with_role(Role::Custodian)
1086 .with_response(Response::Accept)
1087 .build()
1088 .unwrap();
1089
1090 assert_eq!(action.record_id(), "32");
1091 assert_eq!(action.receiving_agent(), "jim");
1092 assert_eq!(*action.role(), Role::Custodian);
1093 assert_eq!(*action.response(), Response::Accept);
1094 }
1095
1096 #[test]
1097 fn test_answer_proposal_action_bytes() {
1100 let action = AnswerProposalActionBuilder::new()
1101 .with_record_id("32".into())
1102 .with_receiving_agent("jim".into())
1103 .with_role(Role::Custodian)
1104 .with_response(Response::Accept)
1105 .build()
1106 .unwrap();
1107
1108 test_from_bytes(action, AnswerProposalAction::from_bytes);
1109 }
1110
1111 #[test]
1112 fn test_revoke_reporter_action_builder() {
1114 let action = RevokeReporterActionBuilder::new()
1115 .with_record_id("32".into())
1116 .with_reporter_id("jim".into())
1117 .with_properties(vec!["egg".into()])
1118 .build()
1119 .unwrap();
1120
1121 assert_eq!(action.record_id(), "32");
1122 assert_eq!(action.reporter_id(), "jim");
1123 assert!(action.properties().iter().any(|x| x == "egg"));
1124 }
1125
1126 #[test]
1127 fn test_revoke_reporter_action_bytes() {
1130 let action = RevokeReporterActionBuilder::new()
1131 .with_record_id("32".into())
1132 .with_reporter_id("jim".into())
1133 .with_properties(vec!["egg".into()])
1134 .build()
1135 .unwrap();
1136
1137 test_from_bytes(action, RevokeReporterAction::from_bytes);
1138 }
1139
1140 #[test]
1141 fn test_payload_builder() {
1143 let action = RevokeReporterActionBuilder::new()
1144 .with_record_id("32".into())
1145 .with_reporter_id("jim".into())
1146 .with_properties(vec!["egg".into()])
1147 .build()
1148 .unwrap();
1149
1150 let payload = TrackAndTracePayloadBuilder::new()
1151 .with_action(Action::RevokeReporter(action.clone()))
1152 .with_timestamp(0)
1153 .build()
1154 .unwrap();
1155
1156 assert_eq!(*payload.action(), Action::RevokeReporter(action));
1157 assert_eq!(*payload.timestamp(), 0);
1158 }
1159
1160 #[test]
1161 fn test_payload_bytes() {
1164 let action = RevokeReporterActionBuilder::new()
1165 .with_record_id("32".into())
1166 .with_reporter_id("jim".into())
1167 .with_properties(vec!["egg".into()])
1168 .build()
1169 .unwrap();
1170
1171 let payload = TrackAndTracePayloadBuilder::new()
1172 .with_action(Action::RevokeReporter(action.clone()))
1173 .with_timestamp(0)
1174 .build()
1175 .unwrap();
1176
1177 test_from_bytes(payload, TrackAndTracePayload::from_bytes);
1178 }
1179}