1use protobuf::Message;
18use protobuf::RepeatedField;
19
20use std::error::Error as StdError;
21
22use crate::protos;
23use crate::protos::{
24 FromBytes, FromNative, FromProto, IntoBytes, IntoNative, IntoProto, ProtoConversionError,
25};
26
27#[derive(Debug, Clone, PartialEq)]
31pub enum DataType {
32 Bytes,
33 Boolean,
34 Number,
35 String,
36 Enum,
37 Struct,
38 LatLong,
39}
40
41impl FromProto<protos::schema_state::PropertyDefinition_DataType> for DataType {
42 fn from_proto(
43 data_type: protos::schema_state::PropertyDefinition_DataType,
44 ) -> Result<Self, ProtoConversionError> {
45 match data_type {
46 protos::schema_state::PropertyDefinition_DataType::BYTES => Ok(DataType::Bytes),
47 protos::schema_state::PropertyDefinition_DataType::BOOLEAN => Ok(DataType::Boolean),
48 protos::schema_state::PropertyDefinition_DataType::NUMBER => Ok(DataType::Number),
49 protos::schema_state::PropertyDefinition_DataType::STRING => Ok(DataType::String),
50 protos::schema_state::PropertyDefinition_DataType::ENUM => Ok(DataType::Enum),
51 protos::schema_state::PropertyDefinition_DataType::STRUCT => Ok(DataType::Struct),
52 protos::schema_state::PropertyDefinition_DataType::LAT_LONG => Ok(DataType::LatLong),
53 protos::schema_state::PropertyDefinition_DataType::UNSET_DATA_TYPE => {
54 Err(ProtoConversionError::InvalidTypeError(
55 "Cannot convert PropertyDefinition_DataType with type unset.".to_string(),
56 ))
57 }
58 }
59 }
60}
61
62impl FromNative<DataType> for protos::schema_state::PropertyDefinition_DataType {
63 fn from_native(data_type: DataType) -> Result<Self, ProtoConversionError> {
64 match data_type {
65 DataType::Bytes => Ok(protos::schema_state::PropertyDefinition_DataType::BYTES),
66 DataType::Boolean => Ok(protos::schema_state::PropertyDefinition_DataType::BOOLEAN),
67 DataType::Number => Ok(protos::schema_state::PropertyDefinition_DataType::NUMBER),
68 DataType::String => Ok(protos::schema_state::PropertyDefinition_DataType::STRING),
69 DataType::Enum => Ok(protos::schema_state::PropertyDefinition_DataType::ENUM),
70 DataType::Struct => Ok(protos::schema_state::PropertyDefinition_DataType::STRUCT),
71 DataType::LatLong => Ok(protos::schema_state::PropertyDefinition_DataType::LAT_LONG),
72 }
73 }
74}
75
76impl IntoProto<protos::schema_state::PropertyDefinition_DataType> for DataType {}
77impl IntoNative<DataType> for protos::schema_state::PropertyDefinition_DataType {}
78
79#[derive(Debug, Clone, PartialEq)]
83pub struct LatLong {
84 latitude: i64,
85 longitude: i64,
86}
87
88impl LatLong {
89 pub fn latitude(&self) -> &i64 {
90 &self.latitude
91 }
92
93 pub fn longitude(&self) -> &i64 {
94 &self.longitude
95 }
96}
97
98impl FromProto<protos::schema_state::LatLong> for LatLong {
99 fn from_proto(lat_long: protos::schema_state::LatLong) -> Result<Self, ProtoConversionError> {
100 Ok(LatLong {
101 latitude: lat_long.get_latitude(),
102 longitude: lat_long.get_longitude(),
103 })
104 }
105}
106
107impl FromNative<LatLong> for protos::schema_state::LatLong {
108 fn from_native(lat_long: LatLong) -> Result<Self, ProtoConversionError> {
109 let mut proto_lat_long = protos::schema_state::LatLong::new();
110 proto_lat_long.set_latitude(*lat_long.latitude());
111 proto_lat_long.set_longitude(*lat_long.longitude());
112 Ok(proto_lat_long)
113 }
114}
115
116impl IntoProto<protos::schema_state::LatLong> for LatLong {}
117impl IntoNative<LatLong> for protos::schema_state::LatLong {}
118
119#[derive(Debug)]
122pub enum LatLongBuildError {
123 InvalidLatitude(i64),
124 InvalidLongitude(i64),
125}
126
127impl StdError for LatLongBuildError {}
128
129impl std::fmt::Display for LatLongBuildError {
130 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
131 match *self {
132 LatLongBuildError::InvalidLatitude(ref s) => write!(
133 f,
134 "Invalid latitude - must in the range of \
135 -90000000 < lat < 90000000, but received: {}",
136 s
137 ),
138 LatLongBuildError::InvalidLongitude(ref s) => write!(
139 f,
140 "Invalid longitude - must in the range of \
141 -180000000 < lat < 180000000, but received: {}",
142 s
143 ),
144 }
145 }
146}
147
148#[derive(Default, Clone, PartialEq)]
150pub struct LatLongBuilder {
151 pub latitude: i64,
152 pub longitude: i64,
153}
154
155impl LatLongBuilder {
156 pub fn new() -> Self {
157 LatLongBuilder::default()
158 }
159
160 pub fn with_lat_long(mut self, latitude: i64, longitude: i64) -> LatLongBuilder {
161 self.latitude = latitude;
162 self.longitude = longitude;
163 self
164 }
165
166 pub fn build(self) -> Result<LatLong, LatLongBuildError> {
167 let latitude = self.latitude;
168 let longitude = self.longitude;
169
170 if latitude < -90_000_000 || latitude > 90_000_000 {
171 Err(LatLongBuildError::InvalidLatitude(latitude))
172 } else if longitude < -180_000_000 || longitude > 180_000_000 {
173 Err(LatLongBuildError::InvalidLongitude(longitude))
174 } else {
175 Ok(LatLong {
176 latitude,
177 longitude,
178 })
179 }
180 }
181}
182
183#[derive(Debug, Clone, PartialEq)]
187pub struct PropertyDefinition {
188 name: String,
189 data_type: DataType,
190 required: bool,
191 description: String,
192 number_exponent: i32,
193 enum_options: Vec<String>,
194 struct_properties: Vec<PropertyDefinition>,
195}
196
197impl PropertyDefinition {
198 pub fn name(&self) -> &str {
199 &self.name
200 }
201
202 pub fn data_type(&self) -> &DataType {
203 &self.data_type
204 }
205
206 pub fn required(&self) -> &bool {
207 &self.required
208 }
209
210 pub fn description(&self) -> &str {
211 &self.description
212 }
213
214 pub fn number_exponent(&self) -> &i32 {
215 &self.number_exponent
216 }
217
218 pub fn enum_options(&self) -> &[String] {
219 &self.enum_options
220 }
221
222 pub fn struct_properties(&self) -> &[PropertyDefinition] {
223 &self.struct_properties
224 }
225}
226
227impl FromProto<protos::schema_state::PropertyDefinition> for PropertyDefinition {
228 fn from_proto(
229 property_definition: protos::schema_state::PropertyDefinition,
230 ) -> Result<Self, ProtoConversionError> {
231 Ok(PropertyDefinition {
232 name: property_definition.get_name().to_string(),
233 data_type: DataType::from_proto(property_definition.get_data_type())?,
234 required: property_definition.get_required(),
235 description: property_definition.get_description().to_string(),
236 number_exponent: property_definition.get_number_exponent(),
237 enum_options: property_definition.get_enum_options().to_vec(),
238 struct_properties: property_definition
239 .get_struct_properties()
240 .iter()
241 .cloned()
242 .map(PropertyDefinition::from_proto)
243 .collect::<Result<Vec<PropertyDefinition>, ProtoConversionError>>()?,
244 })
245 }
246}
247
248impl FromNative<PropertyDefinition> for protos::schema_state::PropertyDefinition {
249 fn from_native(property_definition: PropertyDefinition) -> Result<Self, ProtoConversionError> {
250 let mut proto_property_definition = protos::schema_state::PropertyDefinition::new();
251 proto_property_definition.set_name(property_definition.name().to_string());
252 proto_property_definition
253 .set_data_type(property_definition.data_type().clone().into_proto()?);
254 proto_property_definition.set_required(*property_definition.required());
255 proto_property_definition.set_description(property_definition.description().to_string());
256 proto_property_definition.set_number_exponent(*property_definition.number_exponent());
257 proto_property_definition.set_enum_options(RepeatedField::from_vec(
258 property_definition.enum_options().to_vec(),
259 ));
260 proto_property_definition.set_struct_properties(
261 RepeatedField::from_vec(
262 property_definition.struct_properties().iter().cloned()
263 .map(PropertyDefinition::into_proto)
264 .collect::<Result<Vec<protos::schema_state::PropertyDefinition>, ProtoConversionError>>()?,));
265 Ok(proto_property_definition)
266 }
267}
268
269impl FromBytes<PropertyDefinition> for PropertyDefinition {
270 fn from_bytes(bytes: &[u8]) -> Result<PropertyDefinition, ProtoConversionError> {
271 let proto: protos::schema_state::PropertyDefinition = Message::parse_from_bytes(bytes)
272 .map_err(|_| {
273 ProtoConversionError::SerializationError(
274 "Unable to get PropertyDefinition from bytes".to_string(),
275 )
276 })?;
277 proto.into_native()
278 }
279}
280
281impl IntoBytes for PropertyDefinition {
282 fn into_bytes(self) -> Result<Vec<u8>, ProtoConversionError> {
283 let proto = self.into_proto()?;
284 let bytes = proto.write_to_bytes().map_err(|_| {
285 ProtoConversionError::SerializationError(
286 "Unable to get bytes from PropertyDefinition".to_string(),
287 )
288 })?;
289 Ok(bytes)
290 }
291}
292
293impl IntoProto<protos::schema_state::PropertyDefinition> for PropertyDefinition {}
294impl IntoNative<PropertyDefinition> for protos::schema_state::PropertyDefinition {}
295
296#[derive(Debug)]
299pub enum PropertyDefinitionBuildError {
300 MissingField(String),
301 EmptyVec(String),
302}
303
304impl StdError for PropertyDefinitionBuildError {
305 fn description(&self) -> &str {
306 match *self {
307 PropertyDefinitionBuildError::MissingField(ref msg) => msg,
308 PropertyDefinitionBuildError::EmptyVec(ref msg) => msg,
309 }
310 }
311
312 fn cause(&self) -> Option<&dyn StdError> {
313 match *self {
314 PropertyDefinitionBuildError::MissingField(_) => None,
315 PropertyDefinitionBuildError::EmptyVec(_) => None,
316 }
317 }
318}
319
320impl std::fmt::Display for PropertyDefinitionBuildError {
321 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
322 match *self {
323 PropertyDefinitionBuildError::MissingField(ref s) => write!(f, "MissingField: {}", s),
324 PropertyDefinitionBuildError::EmptyVec(ref s) => write!(f, "EmptyVec: {}", s),
325 }
326 }
327}
328
329#[derive(Default, Clone, PartialEq)]
331pub struct PropertyDefinitionBuilder {
332 pub name: Option<String>,
333 pub data_type: Option<DataType>,
334 pub required: Option<bool>,
335 pub description: Option<String>,
336 pub number_exponent: Option<i32>,
337 pub enum_options: Vec<String>,
338 pub struct_properties: Vec<PropertyDefinition>,
339}
340
341impl PropertyDefinitionBuilder {
342 pub fn new() -> Self {
343 PropertyDefinitionBuilder::default()
344 }
345
346 pub fn with_name(mut self, name: String) -> PropertyDefinitionBuilder {
347 self.name = Some(name);
348 self
349 }
350
351 pub fn with_data_type(mut self, data_type: DataType) -> PropertyDefinitionBuilder {
352 self.data_type = Some(data_type);
353 self
354 }
355
356 pub fn with_required(mut self, required: bool) -> PropertyDefinitionBuilder {
357 self.required = Some(required);
358 self
359 }
360
361 pub fn with_description(mut self, description: String) -> PropertyDefinitionBuilder {
362 self.description = Some(description);
363 self
364 }
365
366 pub fn with_number_exponent(mut self, number_exponent: i32) -> PropertyDefinitionBuilder {
367 self.number_exponent = Some(number_exponent);
368 self
369 }
370
371 pub fn with_enum_options(mut self, enum_options: Vec<String>) -> PropertyDefinitionBuilder {
372 self.enum_options = enum_options;
373 self
374 }
375
376 pub fn with_struct_properties(
377 mut self,
378 struct_properties: Vec<PropertyDefinition>,
379 ) -> PropertyDefinitionBuilder {
380 self.struct_properties = struct_properties;
381 self
382 }
383
384 pub fn build(self) -> Result<PropertyDefinition, PropertyDefinitionBuildError> {
385 let name = self.name.ok_or_else(|| {
386 PropertyDefinitionBuildError::MissingField("'name' field is required".to_string())
387 })?;
388
389 let data_type = self.data_type.ok_or_else(|| {
390 PropertyDefinitionBuildError::MissingField("'data_type' field is required".to_string())
391 })?;
392
393 let required = self.required.unwrap_or(false);
394 let description = self.description.unwrap_or_default();
395
396 let number_exponent = {
397 if data_type == DataType::Number {
398 self.number_exponent.ok_or_else(|| {
399 PropertyDefinitionBuildError::MissingField(
400 "'number_exponent' field is required".to_string(),
401 )
402 })?
403 } else {
404 0
405 }
406 };
407
408 let enum_options = {
409 if data_type == DataType::Enum {
410 if !self.enum_options.is_empty() {
411 self.enum_options
412 } else {
413 return Err(PropertyDefinitionBuildError::EmptyVec(
414 "'enum_options' cannot be empty".to_string(),
415 ));
416 }
417 } else {
418 self.enum_options
419 }
420 };
421
422 let struct_properties = {
423 if data_type == DataType::Struct {
424 if !self.struct_properties.is_empty() {
425 self.struct_properties
426 } else {
427 return Err(PropertyDefinitionBuildError::EmptyVec(
428 "'struct_properties' cannot be empty".to_string(),
429 ));
430 }
431 } else {
432 self.struct_properties
433 }
434 };
435
436 Ok(PropertyDefinition {
437 name,
438 data_type,
439 required,
440 description,
441 number_exponent,
442 enum_options,
443 struct_properties,
444 })
445 }
446}
447
448#[derive(Debug, Clone, PartialEq)]
452pub struct Schema {
453 name: String,
454 description: String,
455 owner: String,
456 properties: Vec<PropertyDefinition>,
457}
458
459impl Schema {
460 pub fn name(&self) -> &str {
461 &self.name
462 }
463
464 pub fn description(&self) -> &str {
465 &self.description
466 }
467
468 pub fn owner(&self) -> &str {
469 &self.owner
470 }
471
472 pub fn properties(&self) -> &[PropertyDefinition] {
473 &self.properties
474 }
475}
476
477impl FromProto<protos::schema_state::Schema> for Schema {
478 fn from_proto(schema: protos::schema_state::Schema) -> Result<Self, ProtoConversionError> {
479 Ok(Schema {
480 name: schema.get_name().to_string(),
481 description: schema.get_description().to_string(),
482 owner: schema.get_owner().to_string(),
483 properties: schema
484 .get_properties()
485 .iter()
486 .cloned()
487 .map(PropertyDefinition::from_proto)
488 .collect::<Result<Vec<PropertyDefinition>, ProtoConversionError>>()?,
489 })
490 }
491}
492
493impl FromNative<Schema> for protos::schema_state::Schema {
494 fn from_native(schema: Schema) -> Result<Self, ProtoConversionError> {
495 let mut proto_schema = protos::schema_state::Schema::new();
496 proto_schema.set_name(schema.name().to_string());
497 proto_schema.set_description(schema.description().to_string());
498 proto_schema.set_owner(schema.owner().to_string());
499 proto_schema.set_properties(RepeatedField::from_vec(
500 schema
501 .properties()
502 .iter()
503 .cloned()
504 .map(PropertyDefinition::into_proto)
505 .collect::<Result<Vec<protos::schema_state::PropertyDefinition>, ProtoConversionError>>()?,
506 ));
507 Ok(proto_schema)
508 }
509}
510
511impl FromBytes<Schema> for Schema {
512 fn from_bytes(bytes: &[u8]) -> Result<Schema, ProtoConversionError> {
513 let proto: protos::schema_state::Schema =
514 Message::parse_from_bytes(bytes).map_err(|_| {
515 ProtoConversionError::SerializationError(
516 "Unable to get Schema from bytes".to_string(),
517 )
518 })?;
519 proto.into_native()
520 }
521}
522
523impl IntoBytes for Schema {
524 fn into_bytes(self) -> Result<Vec<u8>, ProtoConversionError> {
525 let proto = self.into_proto()?;
526 let bytes = proto.write_to_bytes().map_err(|_| {
527 ProtoConversionError::SerializationError("Unable to get bytes from Schema".to_string())
528 })?;
529 Ok(bytes)
530 }
531}
532
533impl IntoProto<protos::schema_state::Schema> for Schema {}
534impl IntoNative<Schema> for protos::schema_state::Schema {}
535
536#[derive(Debug)]
539pub enum SchemaBuildError {
540 MissingField(String),
541}
542
543impl StdError for SchemaBuildError {
544 fn description(&self) -> &str {
545 match *self {
546 SchemaBuildError::MissingField(ref msg) => msg,
547 }
548 }
549
550 fn cause(&self) -> Option<&dyn StdError> {
551 match *self {
552 SchemaBuildError::MissingField(_) => None,
553 }
554 }
555}
556
557impl std::fmt::Display for SchemaBuildError {
558 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
559 match *self {
560 SchemaBuildError::MissingField(ref s) => write!(f, "MissingField: {}", s),
561 }
562 }
563}
564
565#[derive(Default, Clone)]
567pub struct SchemaBuilder {
568 pub name: Option<String>,
569 pub description: Option<String>,
570 pub owner: Option<String>,
571 pub properties: Vec<PropertyDefinition>,
572}
573
574impl SchemaBuilder {
575 pub fn new() -> Self {
576 SchemaBuilder::default()
577 }
578
579 pub fn with_name(mut self, name: String) -> SchemaBuilder {
580 self.name = Some(name);
581 self
582 }
583
584 pub fn with_description(mut self, description: String) -> SchemaBuilder {
585 self.description = Some(description);
586 self
587 }
588
589 pub fn with_owner(mut self, owner: String) -> SchemaBuilder {
590 self.owner = Some(owner);
591 self
592 }
593
594 pub fn with_properties(mut self, properties: Vec<PropertyDefinition>) -> SchemaBuilder {
595 self.properties = properties;
596 self
597 }
598
599 pub fn build(self) -> Result<Schema, SchemaBuildError> {
600 let name = self.name.ok_or_else(|| {
601 SchemaBuildError::MissingField("'name' field is required".to_string())
602 })?;
603
604 let owner = self.owner.ok_or_else(|| {
605 SchemaBuildError::MissingField("'owner' field is required".to_string())
606 })?;
607
608 let description = self.description.unwrap_or_else(|| "".to_string());
609 let properties = {
610 if !self.properties.is_empty() {
611 self.properties
612 } else {
613 return Err(SchemaBuildError::MissingField(
614 "'properties' field is required".to_string(),
615 ));
616 }
617 };
618
619 Ok(Schema {
620 name,
621 description,
622 owner,
623 properties,
624 })
625 }
626}
627
628#[derive(Debug, Clone, PartialEq)]
630pub struct SchemaList {
631 schemas: Vec<Schema>,
632}
633
634impl SchemaList {
635 pub fn schemas(&self) -> &[Schema] {
636 &self.schemas
637 }
638}
639
640impl FromProto<protos::schema_state::SchemaList> for SchemaList {
641 fn from_proto(
642 schema_list: protos::schema_state::SchemaList,
643 ) -> Result<Self, ProtoConversionError> {
644 Ok(SchemaList {
645 schemas: schema_list
646 .get_schemas()
647 .iter()
648 .cloned()
649 .map(Schema::from_proto)
650 .collect::<Result<Vec<Schema>, ProtoConversionError>>()?,
651 })
652 }
653}
654
655impl FromNative<SchemaList> for protos::schema_state::SchemaList {
656 fn from_native(schema_list: SchemaList) -> Result<Self, ProtoConversionError> {
657 let mut schema_list_proto = protos::schema_state::SchemaList::new();
658
659 schema_list_proto.set_schemas(RepeatedField::from_vec(
660 schema_list
661 .schemas()
662 .iter()
663 .cloned()
664 .map(Schema::into_proto)
665 .collect::<Result<Vec<protos::schema_state::Schema>, ProtoConversionError>>()?,
666 ));
667
668 Ok(schema_list_proto)
669 }
670}
671
672impl FromBytes<SchemaList> for SchemaList {
673 fn from_bytes(bytes: &[u8]) -> Result<SchemaList, ProtoConversionError> {
674 let proto: protos::schema_state::SchemaList =
675 Message::parse_from_bytes(bytes).map_err(|_| {
676 ProtoConversionError::SerializationError(
677 "Unable to get SchemaList from bytes".to_string(),
678 )
679 })?;
680 proto.into_native()
681 }
682}
683
684impl IntoBytes for SchemaList {
685 fn into_bytes(self) -> Result<Vec<u8>, ProtoConversionError> {
686 let proto = self.into_proto()?;
687 let bytes = proto.write_to_bytes().map_err(|_| {
688 ProtoConversionError::SerializationError(
689 "Unable to get bytes from SchemaList".to_string(),
690 )
691 })?;
692 Ok(bytes)
693 }
694}
695
696impl IntoProto<protos::schema_state::SchemaList> for SchemaList {}
697impl IntoNative<SchemaList> for protos::schema_state::SchemaList {}
698
699#[derive(Debug)]
702pub enum SchemaListBuildError {
703 MissingField(String),
704}
705
706impl StdError for SchemaListBuildError {
707 fn description(&self) -> &str {
708 match *self {
709 SchemaListBuildError::MissingField(ref msg) => msg,
710 }
711 }
712
713 fn cause(&self) -> Option<&dyn StdError> {
714 match *self {
715 SchemaListBuildError::MissingField(_) => None,
716 }
717 }
718}
719
720impl std::fmt::Display for SchemaListBuildError {
721 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
722 match *self {
723 SchemaListBuildError::MissingField(ref s) => write!(f, "MissingField: {}", s),
724 }
725 }
726}
727
728#[derive(Default, Clone)]
730pub struct SchemaListBuilder {
731 pub schemas: Vec<Schema>,
732}
733
734impl SchemaListBuilder {
735 pub fn new() -> Self {
736 SchemaListBuilder::default()
737 }
738
739 pub fn with_schemas(mut self, schemas: Vec<Schema>) -> SchemaListBuilder {
740 self.schemas = schemas;
741 self
742 }
743
744 pub fn build(self) -> Result<SchemaList, SchemaListBuildError> {
745 let schemas = {
746 if self.schemas.is_empty() {
747 return Err(SchemaListBuildError::MissingField(
748 "'schemas' cannot be empty".to_string(),
749 ));
750 } else {
751 self.schemas
752 }
753 };
754
755 Ok(SchemaList { schemas })
756 }
757}
758
759#[derive(Debug, Clone, PartialEq)]
763pub struct PropertyValue {
764 name: String,
765 data_type: DataType,
766 bytes_value: Vec<u8>,
767 boolean_value: bool,
768 number_value: i64,
769 string_value: String,
770 enum_value: u32,
771 struct_values: Vec<PropertyValue>,
772 lat_long_value: LatLong,
773}
774
775impl PropertyValue {
776 pub fn name(&self) -> &str {
777 &self.name
778 }
779
780 pub fn data_type(&self) -> &DataType {
781 &self.data_type
782 }
783
784 pub fn bytes_value(&self) -> &[u8] {
785 &self.bytes_value
786 }
787
788 pub fn boolean_value(&self) -> &bool {
789 &self.boolean_value
790 }
791
792 pub fn number_value(&self) -> &i64 {
793 &self.number_value
794 }
795
796 pub fn string_value(&self) -> &str {
797 &self.string_value
798 }
799
800 pub fn enum_value(&self) -> &u32 {
801 &self.enum_value
802 }
803
804 pub fn struct_values(&self) -> &[PropertyValue] {
805 &self.struct_values
806 }
807
808 pub fn lat_long_value(&self) -> &LatLong {
809 &self.lat_long_value
810 }
811}
812
813impl FromProto<protos::schema_state::PropertyValue> for PropertyValue {
814 fn from_proto(
815 property_value: protos::schema_state::PropertyValue,
816 ) -> Result<Self, ProtoConversionError> {
817 Ok(PropertyValue {
818 name: property_value.get_name().to_string(),
819 data_type: DataType::from_proto(property_value.get_data_type())?,
820 bytes_value: property_value.get_bytes_value().to_vec(),
821 boolean_value: property_value.get_boolean_value(),
822 number_value: property_value.get_number_value(),
823 string_value: property_value.get_string_value().to_string(),
824 enum_value: property_value.get_enum_value(),
825 struct_values: property_value
826 .get_struct_values()
827 .iter()
828 .cloned()
829 .map(PropertyValue::from_proto)
830 .collect::<Result<Vec<PropertyValue>, ProtoConversionError>>()?,
831 lat_long_value: property_value.get_lat_long_value().clone().into_native()?,
832 })
833 }
834}
835
836impl FromNative<PropertyValue> for protos::schema_state::PropertyValue {
837 fn from_native(property_value: PropertyValue) -> Result<Self, ProtoConversionError> {
838 let mut proto_property_value = protos::schema_state::PropertyValue::new();
839 proto_property_value.set_name(property_value.name().to_string());
840 proto_property_value.set_data_type(property_value.data_type().clone().into_proto()?);
841 proto_property_value.set_bytes_value(property_value.bytes_value().to_vec());
842 proto_property_value.set_boolean_value(*property_value.boolean_value());
843 proto_property_value.set_number_value(*property_value.number_value());
844 proto_property_value.set_string_value(property_value.string_value().to_string());
845 proto_property_value.set_enum_value(*property_value.enum_value());
846 proto_property_value.set_struct_values(RepeatedField::from_vec(
847 property_value
848 .struct_values()
849 .iter()
850 .cloned()
851 .map(PropertyValue::into_proto)
852 .collect::<Result<Vec<protos::schema_state::PropertyValue>, ProtoConversionError>>(
853 )?,
854 ));
855 proto_property_value
856 .set_lat_long_value(property_value.lat_long_value().clone().into_proto()?);
857 Ok(proto_property_value)
858 }
859}
860
861impl FromBytes<PropertyValue> for PropertyValue {
862 fn from_bytes(bytes: &[u8]) -> Result<PropertyValue, ProtoConversionError> {
863 let proto: protos::schema_state::PropertyValue =
864 Message::parse_from_bytes(bytes).map_err(|_| {
865 ProtoConversionError::SerializationError(
866 "Unable to get PropertyValue from bytes".to_string(),
867 )
868 })?;
869 proto.into_native()
870 }
871}
872
873impl IntoBytes for PropertyValue {
874 fn into_bytes(self) -> Result<Vec<u8>, ProtoConversionError> {
875 let proto = self.into_proto()?;
876 let bytes = proto.write_to_bytes().map_err(|_| {
877 ProtoConversionError::SerializationError(
878 "Unable to get bytes from PropertyValue".to_string(),
879 )
880 })?;
881 Ok(bytes)
882 }
883}
884
885impl IntoProto<protos::schema_state::PropertyValue> for PropertyValue {}
886impl IntoNative<PropertyValue> for protos::schema_state::PropertyValue {}
887
888#[derive(Debug)]
891pub enum PropertyValueBuildError {
892 MissingField(String),
893}
894
895impl StdError for PropertyValueBuildError {
896 fn description(&self) -> &str {
897 match *self {
898 PropertyValueBuildError::MissingField(ref msg) => msg,
899 }
900 }
901
902 fn cause(&self) -> Option<&dyn StdError> {
903 match *self {
904 PropertyValueBuildError::MissingField(_) => None,
905 }
906 }
907}
908
909impl std::fmt::Display for PropertyValueBuildError {
910 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
911 match *self {
912 PropertyValueBuildError::MissingField(ref s) => write!(f, "MissingField: {}", s),
913 }
914 }
915}
916
917#[derive(Default, Clone)]
919pub struct PropertyValueBuilder {
920 pub name: Option<String>,
921 pub data_type: Option<DataType>,
922 pub bytes_value: Option<Vec<u8>>,
923 pub boolean_value: Option<bool>,
924 pub number_value: Option<i64>,
925 pub string_value: Option<String>,
926 pub enum_value: Option<u32>,
927 pub struct_values: Vec<PropertyValue>,
928 pub lat_long_value: Option<LatLong>,
929}
930
931impl PropertyValueBuilder {
932 pub fn new() -> Self {
933 PropertyValueBuilder::default()
934 }
935
936 pub fn with_name(mut self, name: String) -> PropertyValueBuilder {
937 self.name = Some(name);
938 self
939 }
940
941 pub fn with_data_type(mut self, data_type: DataType) -> PropertyValueBuilder {
942 self.data_type = Some(data_type);
943 self
944 }
945
946 pub fn with_bytes_value(mut self, bytes: Vec<u8>) -> PropertyValueBuilder {
947 self.bytes_value = Some(bytes);
948 self
949 }
950
951 pub fn with_boolean_value(mut self, boolean: bool) -> PropertyValueBuilder {
952 self.boolean_value = Some(boolean);
953 self
954 }
955
956 pub fn with_number_value(mut self, number: i64) -> PropertyValueBuilder {
957 self.number_value = Some(number);
958 self
959 }
960
961 pub fn with_enum_value(mut self, enum_value: u32) -> PropertyValueBuilder {
962 self.enum_value = Some(enum_value);
963 self
964 }
965
966 pub fn with_string_value(mut self, string: String) -> PropertyValueBuilder {
967 self.string_value = Some(string);
968 self
969 }
970
971 pub fn with_struct_values(mut self, struct_values: Vec<PropertyValue>) -> PropertyValueBuilder {
972 self.struct_values = struct_values;
973 self
974 }
975
976 pub fn with_lat_long_value(mut self, lat_long_value: LatLong) -> PropertyValueBuilder {
977 self.lat_long_value = Some(lat_long_value);
978 self
979 }
980
981 pub fn build(self) -> Result<PropertyValue, PropertyValueBuildError> {
982 let name = self.name.ok_or_else(|| {
983 PropertyValueBuildError::MissingField("'name' field is required".to_string())
984 })?;
985
986 let data_type = self.data_type.ok_or_else(|| {
987 PropertyValueBuildError::MissingField("'data_type' field is required".to_string())
988 })?;
989
990 let bytes_value = {
991 if data_type == DataType::Bytes {
992 self.bytes_value.ok_or_else(|| {
993 PropertyValueBuildError::MissingField(
994 "'bytes_value' field is required".to_string(),
995 )
996 })?
997 } else {
998 vec![]
999 }
1000 };
1001
1002 let boolean_value = {
1003 if data_type == DataType::Boolean {
1004 self.boolean_value.ok_or_else(|| {
1005 PropertyValueBuildError::MissingField(
1006 "'boolean_value' field is required".to_string(),
1007 )
1008 })?
1009 } else {
1010 false
1011 }
1012 };
1013
1014 let number_value = {
1015 if data_type == DataType::Number {
1016 self.number_value.ok_or_else(|| {
1017 PropertyValueBuildError::MissingField(
1018 "'number_value' field is required".to_string(),
1019 )
1020 })?
1021 } else {
1022 0
1023 }
1024 };
1025
1026 let string_value = {
1027 if data_type == DataType::String {
1028 self.string_value.ok_or_else(|| {
1029 PropertyValueBuildError::MissingField(
1030 "'string_value' field is required".to_string(),
1031 )
1032 })?
1033 } else {
1034 "".to_string()
1035 }
1036 };
1037
1038 let enum_value = {
1039 if data_type == DataType::Enum {
1040 self.enum_value.ok_or_else(|| {
1041 PropertyValueBuildError::MissingField(
1042 "'enum_value' field is required".to_string(),
1043 )
1044 })?
1045 } else {
1046 0
1047 }
1048 };
1049
1050 let struct_values = {
1051 if data_type == DataType::Struct {
1052 if !self.struct_values.is_empty() {
1053 self.struct_values
1054 } else {
1055 return Err(PropertyValueBuildError::MissingField(
1056 "'struct_values' cannot be empty".to_string(),
1057 ));
1058 }
1059 } else {
1060 self.struct_values
1061 }
1062 };
1063
1064 let lat_long_value = {
1065 if data_type == DataType::LatLong {
1066 self.lat_long_value.ok_or_else(|| {
1067 PropertyValueBuildError::MissingField(
1068 "'lat_long_value' field is required".to_string(),
1069 )
1070 })?
1071 } else {
1072 LatLong {
1073 latitude: 0,
1074 longitude: 0,
1075 }
1076 }
1077 };
1078
1079 Ok(PropertyValue {
1080 name,
1081 data_type,
1082 bytes_value,
1083 boolean_value,
1084 number_value,
1085 string_value,
1086 enum_value,
1087 struct_values,
1088 lat_long_value,
1089 })
1090 }
1091}
1092
1093#[cfg(test)]
1094mod tests {
1095 use super::*;
1096
1097 #[test]
1098 fn check_property_definition_builder_string() {
1100 let builder = PropertyDefinitionBuilder::new();
1101 let property_definition = builder
1102 .with_name("TEST".to_string())
1103 .with_data_type(DataType::String)
1104 .with_description("Optional".to_string())
1105 .build()
1106 .unwrap();
1107
1108 assert_eq!(property_definition.name, "TEST");
1109 assert_eq!(property_definition.data_type, DataType::String);
1110 assert_eq!(property_definition.description, "Optional");
1111 }
1112
1113 #[test]
1114 fn check_property_definition_builder_enum() {
1116 let builder = PropertyDefinitionBuilder::new();
1117 let property_definition = builder
1118 .with_name("TEST".to_string())
1119 .with_data_type(DataType::Enum)
1120 .with_description("Optional".to_string())
1121 .with_enum_options(vec![
1122 "One".to_string(),
1123 "Two".to_string(),
1124 "Three".to_string(),
1125 ])
1126 .build()
1127 .unwrap();
1128
1129 assert_eq!(property_definition.name, "TEST");
1130 assert_eq!(property_definition.data_type, DataType::Enum);
1131 assert_eq!(property_definition.description, "Optional");
1132 assert_eq!(
1133 property_definition.enum_options,
1134 vec!["One".to_string(), "Two".to_string(), "Three".to_string()]
1135 );
1136 }
1137
1138 #[test]
1139 fn check_property_definition_builder_struct() {
1141 let builder = PropertyDefinitionBuilder::new();
1142 let struct_string = builder
1143 .with_name("TEST".to_string())
1144 .with_data_type(DataType::Enum)
1145 .with_description("Optional".to_string())
1146 .with_enum_options(vec![
1147 "One".to_string(),
1148 "Two".to_string(),
1149 "Three".to_string(),
1150 ])
1151 .build()
1152 .unwrap();
1153
1154 let builder = PropertyDefinitionBuilder::new();
1155 let property_definition = builder
1156 .with_name("TEST_STRUCT".to_string())
1157 .with_data_type(DataType::Struct)
1158 .with_description("Optional".to_string())
1159 .with_struct_properties(vec![struct_string.clone()])
1160 .build()
1161 .unwrap();
1162
1163 assert_eq!(property_definition.name, "TEST_STRUCT");
1164 assert_eq!(property_definition.data_type, DataType::Struct);
1165 assert_eq!(property_definition.description, "Optional");
1166 assert_eq!(property_definition.struct_properties, vec![struct_string]);
1167 }
1168
1169 #[test]
1170 fn check_property_definition_bytes() {
1173 let builder = PropertyDefinitionBuilder::new();
1174 let original = builder
1175 .with_name("TEST".to_string())
1176 .with_data_type(DataType::String)
1177 .with_description("Optional".to_string())
1178 .build()
1179 .unwrap();
1180
1181 let bytes = original.clone().into_bytes().unwrap();
1182
1183 let property_definition = PropertyDefinition::from_bytes(&bytes).unwrap();
1184 assert_eq!(property_definition, original);
1185 }
1186
1187 #[test]
1188 fn check_schema_builder() {
1191 let builder = PropertyDefinitionBuilder::new();
1192 let property_definition = builder
1193 .with_name("TEST".to_string())
1194 .with_data_type(DataType::Enum)
1195 .with_description("Optional".to_string())
1196 .with_enum_options(vec![
1197 "One".to_string(),
1198 "Two".to_string(),
1199 "Three".to_string(),
1200 ])
1201 .build()
1202 .unwrap();
1203
1204 let builder = SchemaBuilder::new();
1205 let schema = builder
1206 .with_name("TestSchema".to_string())
1207 .with_description("Test Schema".to_string())
1208 .with_owner("owner".to_string())
1209 .with_properties(vec![property_definition.clone()])
1210 .build()
1211 .unwrap();
1212
1213 assert_eq!(schema.name, "TestSchema");
1214 assert_eq!(schema.description, "Test Schema");
1215 assert_eq!(schema.owner, "owner");
1216 assert_eq!(schema.properties, vec![property_definition]);
1217 }
1218
1219 #[test]
1220 fn check_schema_bytes() {
1223 let builder = PropertyDefinitionBuilder::new();
1224 let property_definition = builder
1225 .with_name("TEST".to_string())
1226 .with_data_type(DataType::Enum)
1227 .with_description("Optional".to_string())
1228 .with_enum_options(vec![
1229 "One".to_string(),
1230 "Two".to_string(),
1231 "Three".to_string(),
1232 ])
1233 .build()
1234 .unwrap();
1235
1236 let builder = SchemaBuilder::new();
1237 let original = builder
1238 .with_name("TestSchema".to_string())
1239 .with_description("Test Schema".to_string())
1240 .with_owner("owner".to_string())
1241 .with_properties(vec![property_definition.clone()])
1242 .build()
1243 .unwrap();
1244
1245 let bytes = original.clone().into_bytes().unwrap();
1246
1247 let schema = Schema::from_bytes(&bytes).unwrap();
1248 assert_eq!(schema, original);
1249 }
1250
1251 #[test]
1252 fn check_property_value_builder_string() {
1254 let builder = PropertyValueBuilder::new();
1255 let property_value = builder
1256 .with_name("TEST".to_string())
1257 .with_data_type(DataType::String)
1258 .with_string_value("String value".to_string())
1259 .build()
1260 .unwrap();
1261
1262 assert_eq!(property_value.name, "TEST");
1263 assert_eq!(property_value.data_type, DataType::String);
1264 assert_eq!(property_value.string_value, "String value");
1265 }
1266
1267 #[test]
1268 fn check_property_value_builder_struct() {
1270 let builder = PropertyValueBuilder::new();
1271 let string_value = builder
1272 .with_name("TEST".to_string())
1273 .with_data_type(DataType::String)
1274 .with_string_value("String value".to_string())
1275 .build()
1276 .unwrap();
1277
1278 let builder = PropertyValueBuilder::new();
1279 let property_value = builder
1280 .with_name("TEST_STRUCT".to_string())
1281 .with_data_type(DataType::Struct)
1282 .with_struct_values(vec![string_value.clone()])
1283 .build()
1284 .unwrap();
1285
1286 assert_eq!(property_value.name, "TEST_STRUCT");
1287 assert_eq!(property_value.data_type, DataType::Struct);
1288 assert_eq!(property_value.struct_values, vec![string_value]);
1289 }
1290
1291 #[test]
1292 fn check_property_value_builder_lat_long() {
1294 let lat_long = LatLong {
1295 latitude: 44977753,
1296 longitude: -93265015,
1297 };
1298 let builder = PropertyValueBuilder::new();
1299 let property_value = builder
1300 .with_name("TEST".to_string())
1301 .with_data_type(DataType::LatLong)
1302 .with_lat_long_value(lat_long.clone())
1303 .build()
1304 .unwrap();
1305
1306 assert_eq!(property_value.name, "TEST");
1307 assert_eq!(property_value.data_type, DataType::LatLong);
1308 assert_eq!(property_value.lat_long_value, lat_long);
1309 }
1310
1311 #[test]
1312 fn check_property_value_bytes() {
1315 let builder = PropertyValueBuilder::new();
1316 let original = builder
1317 .with_name("TEST".to_string())
1318 .with_data_type(DataType::String)
1319 .with_string_value("String value".to_string())
1320 .build()
1321 .unwrap();
1322
1323 let bytes = original.clone().into_bytes().unwrap();
1324
1325 let property_value = PropertyValue::from_bytes(&bytes).unwrap();
1326 assert_eq!(property_value, original);
1327 }
1328}