#[cfg(feature = "diesel")]
pub(in crate) mod diesel;
pub mod error;
use crate::paging::Paging;
#[cfg(feature = "diesel")]
pub use self::diesel::{DieselConnectionProductStore, DieselProductStore};
pub use error::{ProductBuilderError, ProductStoreError};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Product {
product_id: String,
product_address: String,
product_namespace: String,
owner: String,
start_commit_num: i64,
end_commit_num: i64,
service_id: Option<String>,
last_updated: Option<i64>,
properties: Vec<PropertyValue>,
}
impl Product {
pub fn product_id(&self) -> &str {
&self.product_id
}
pub fn product_address(&self) -> &str {
&self.product_address
}
pub fn product_namespace(&self) -> &str {
&self.product_namespace
}
pub fn owner(&self) -> &str {
&self.owner
}
pub fn start_commit_num(&self) -> &i64 {
&self.start_commit_num
}
pub fn end_commit_num(&self) -> &i64 {
&self.end_commit_num
}
pub fn service_id(&self) -> Option<&str> {
self.service_id.as_deref()
}
pub fn last_updated(&self) -> Option<&i64> {
self.last_updated.as_ref()
}
pub fn properties(&self) -> Vec<PropertyValue> {
self.properties.to_vec()
}
}
#[derive(Default, Clone)]
pub struct ProductBuilder {
product_id: String,
product_address: String,
product_namespace: String,
owner: String,
start_commit_num: i64,
end_commit_num: i64,
service_id: Option<String>,
last_updated: Option<i64>,
properties: Vec<PropertyValue>,
}
impl ProductBuilder {
pub fn with_product_id(mut self, product_id: String) -> Self {
self.product_id = product_id;
self
}
pub fn with_product_address(mut self, product_address: String) -> Self {
self.product_address = product_address;
self
}
pub fn with_product_namespace(mut self, product_namespace: String) -> Self {
self.product_namespace = product_namespace;
self
}
pub fn with_owner(mut self, owner: String) -> Self {
self.owner = owner;
self
}
pub fn with_start_commit_number(mut self, start_commit_num: i64) -> Self {
self.start_commit_num = start_commit_num;
self
}
pub fn with_end_commit_number(mut self, end_commit_num: i64) -> Self {
self.end_commit_num = end_commit_num;
self
}
pub fn with_service_id(mut self, service_id: Option<String>) -> Self {
self.service_id = service_id;
self
}
pub fn with_last_updated(mut self, last_updated: Option<i64>) -> Self {
self.last_updated = last_updated;
self
}
pub fn with_properties(mut self, properties: Vec<PropertyValue>) -> Self {
self.properties = properties;
self
}
pub fn build(self) -> Result<Product, ProductBuilderError> {
let ProductBuilder {
product_id,
product_address,
product_namespace,
owner,
start_commit_num,
end_commit_num,
service_id,
last_updated,
properties,
} = self;
if product_id.is_empty() {
return Err(ProductBuilderError::MissingRequiredField(
"Missing product_id".to_string(),
));
};
if product_address.is_empty() {
return Err(ProductBuilderError::MissingRequiredField(
"Missing product_address".to_string(),
));
};
if product_namespace.is_empty() {
return Err(ProductBuilderError::MissingRequiredField(
"Missing product_namespace".to_string(),
));
};
if owner.is_empty() {
return Err(ProductBuilderError::MissingRequiredField(
"Missing owner".to_string(),
));
};
if start_commit_num >= end_commit_num {
return Err(ProductBuilderError::MissingRequiredField(
"start_commit_number must be less than end_commit_num".to_string(),
));
};
if end_commit_num <= start_commit_num {
return Err(ProductBuilderError::MissingRequiredField(
"end_commit_number must be greater than start_commit_num".to_string(),
));
};
Ok(Product {
product_id,
product_address,
product_namespace,
owner,
start_commit_num,
end_commit_num,
service_id,
last_updated,
properties,
})
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PropertyValue {
product_id: String,
product_address: String,
property_name: String,
data_type: String,
bytes_value: Option<Vec<u8>>,
boolean_value: Option<bool>,
number_value: Option<i64>,
string_value: Option<String>,
enum_value: Option<i32>,
struct_values: Vec<PropertyValue>,
lat_long_value: Option<LatLongValue>,
start_commit_num: i64,
end_commit_num: i64,
service_id: Option<String>,
}
impl PropertyValue {
pub fn product_id(&self) -> &str {
&self.product_id
}
pub fn product_address(&self) -> &str {
&self.product_address
}
pub fn property_name(&self) -> &str {
&self.property_name
}
pub fn data_type(&self) -> &str {
&self.data_type
}
pub fn bytes_value(&self) -> Option<Vec<u8>> {
self.bytes_value.clone()
}
pub fn boolean_value(&self) -> Option<bool> {
self.boolean_value
}
pub fn number_value(&self) -> Option<i64> {
self.number_value
}
pub fn string_value(&self) -> Option<&str> {
self.string_value.as_deref()
}
pub fn enum_value(&self) -> Option<i32> {
self.enum_value
}
pub fn struct_values(&self) -> Vec<PropertyValue> {
self.struct_values.clone()
}
pub fn lat_long_value(&self) -> Option<LatLongValue> {
self.lat_long_value.as_ref().cloned()
}
pub fn start_commit_num(&self) -> &i64 {
&self.start_commit_num
}
pub fn end_commit_num(&self) -> &i64 {
&self.end_commit_num
}
pub fn service_id(&self) -> Option<&str> {
self.service_id.as_deref()
}
}
#[derive(Default, Clone)]
pub struct PropertyValueBuilder {
product_id: String,
product_address: String,
property_name: String,
data_type: String,
bytes_value: Option<Vec<u8>>,
boolean_value: Option<bool>,
number_value: Option<i64>,
string_value: Option<String>,
enum_value: Option<i32>,
struct_values: Vec<PropertyValue>,
lat_long_value: Option<LatLongValue>,
start_commit_num: i64,
end_commit_num: i64,
service_id: Option<String>,
}
impl PropertyValueBuilder {
pub fn with_product_id(mut self, product_id: String) -> Self {
self.product_id = product_id;
self
}
pub fn with_product_address(mut self, product_address: String) -> Self {
self.product_address = product_address;
self
}
pub fn with_property_name(mut self, property_name: String) -> Self {
self.property_name = property_name;
self
}
pub fn with_data_type(mut self, data_type: String) -> Self {
self.data_type = data_type;
self
}
pub fn with_bytes_value(mut self, bytes_value: Option<Vec<u8>>) -> Self {
self.bytes_value = bytes_value;
self
}
pub fn with_boolean_value(mut self, boolean_value: Option<bool>) -> Self {
self.boolean_value = boolean_value;
self
}
pub fn with_number_value(mut self, number_value: Option<i64>) -> Self {
self.number_value = number_value;
self
}
pub fn with_string_value(mut self, string_value: Option<String>) -> Self {
self.string_value = string_value;
self
}
pub fn with_enum_value(mut self, enum_value: Option<i32>) -> Self {
self.enum_value = enum_value;
self
}
pub fn with_struct_values(mut self, struct_values: Vec<PropertyValue>) -> Self {
self.struct_values = struct_values;
self
}
pub fn with_lat_long_value(mut self, lat_long_value: Option<LatLongValue>) -> Self {
self.lat_long_value = lat_long_value;
self
}
pub fn with_start_commit_number(mut self, start_commit_num: i64) -> Self {
self.start_commit_num = start_commit_num;
self
}
pub fn with_end_commit_number(mut self, end_commit_num: i64) -> Self {
self.end_commit_num = end_commit_num;
self
}
pub fn with_service_id(mut self, service_id: Option<String>) -> Self {
self.service_id = service_id;
self
}
pub fn build(self) -> Result<PropertyValue, ProductBuilderError> {
let PropertyValueBuilder {
product_id,
product_address,
property_name,
data_type,
bytes_value,
boolean_value,
number_value,
string_value,
enum_value,
struct_values,
lat_long_value,
start_commit_num,
end_commit_num,
service_id,
} = self;
if product_id.is_empty() {
return Err(ProductBuilderError::MissingRequiredField(
"Missing product_id".to_string(),
));
};
if product_address.is_empty() {
return Err(ProductBuilderError::MissingRequiredField(
"Missing product_address".to_string(),
));
};
if property_name.is_empty() {
return Err(ProductBuilderError::MissingRequiredField(
"Missing product_name".to_string(),
));
};
if data_type.is_empty() {
return Err(ProductBuilderError::MissingRequiredField(
"Missing data_type".to_string(),
));
};
if start_commit_num >= end_commit_num {
return Err(ProductBuilderError::MissingRequiredField(
"start_commit_number must be less than end_commit_num".to_string(),
));
};
if end_commit_num <= start_commit_num {
return Err(ProductBuilderError::MissingRequiredField(
"end_commit_number must be greater than start_commit_num".to_string(),
));
};
Ok(PropertyValue {
product_id,
product_address,
property_name,
data_type,
bytes_value,
boolean_value,
number_value,
string_value,
enum_value,
struct_values,
lat_long_value,
start_commit_num,
end_commit_num,
service_id,
})
}
}
#[derive(Debug, Clone)]
pub struct ProductList {
data: Vec<Product>,
paging: Paging,
}
impl ProductList {
pub fn new(data: Vec<Product>, paging: Paging) -> Self {
Self { data, paging }
}
pub fn data(&self) -> Vec<Product> {
self.data.to_vec()
}
pub fn paging(&self) -> &Paging {
&self.paging
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LatLongValue {
pub latitude: i64,
pub longitude: i64,
}
pub trait ProductStore {
fn add_product(&self, product: Product) -> Result<(), ProductStoreError>;
fn get_product(
&self,
product_id: &str,
service_id: Option<&str>,
) -> Result<Option<Product>, ProductStoreError>;
fn list_products(
&self,
service_id: Option<&str>,
offset: i64,
limit: i64,
) -> Result<ProductList, ProductStoreError>;
fn update_product(
&self,
product_id: &str,
service_id: Option<&str>,
current_commit_num: i64,
) -> Result<(), ProductStoreError>;
fn delete_product(
&self,
address: &str,
current_commit_num: i64,
) -> Result<(), ProductStoreError>;
}
impl<PS> ProductStore for Box<PS>
where
PS: ProductStore + ?Sized,
{
fn add_product(&self, product: Product) -> Result<(), ProductStoreError> {
(**self).add_product(product)
}
fn get_product(
&self,
product_id: &str,
service_id: Option<&str>,
) -> Result<Option<Product>, ProductStoreError> {
(**self).get_product(product_id, service_id)
}
fn list_products(
&self,
service_id: Option<&str>,
offset: i64,
limit: i64,
) -> Result<ProductList, ProductStoreError> {
(**self).list_products(service_id, offset, limit)
}
fn update_product(
&self,
product_id: &str,
service_id: Option<&str>,
current_commit_num: i64,
) -> Result<(), ProductStoreError> {
(**self).update_product(product_id, service_id, current_commit_num)
}
fn delete_product(
&self,
address: &str,
current_commit_num: i64,
) -> Result<(), ProductStoreError> {
(**self).delete_product(address, current_commit_num)
}
}