use serde::{Deserialize, Serialize};
use serde_json::Value;
use serde_this_or_that::as_f64;
#[derive(Serialize, Deserialize, Clone)]
pub enum HashType {
SHA256,
SHA512,
}
#[derive(Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct FileHash {
pub r#type: HashType,
pub value: Option<String>,
}
#[derive(Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct FileInformation {
pub path: Option<String>,
pub hash: Option<Vec<FileHash>>,
pub created_at: Option<String>,
pub modified_at: Option<String>,
}
#[derive(Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct DeviceInformation {
pub id: Option<String>,
pub manufacturer: Option<String>,
pub model: Option<String>,
pub screen_size: Option<String>,
pub language: Option<String>,
pub locale: Option<String>,
}
#[derive(Serialize, Deserialize, Clone)]
pub enum NetworkType {
Wifi,
Cellular,
}
#[derive(Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct NetworkInformation {
pub network_type: Option<NetworkType>,
pub network_name: Option<String>,
pub ipv4: Option<String>,
pub ipv6: Option<String>,
pub cell_info: Option<String>,
}
#[derive(Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct LocationInformation {
pub longitude: Option<f64>,
pub latitude: Option<f64>,
pub time: Option<String>,
pub bearing: Option<String>,
pub accuracy: Option<String>,
pub altitude: Option<String>,
pub provider: Option<String>,
pub speed: Option<String>,
}
#[derive(Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct ExtendedInformation {
pub info: Option<Value>,
}
#[derive(Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct ProofModeJSON {
pub version: String,
pub file: FileInformation,
pub device: DeviceInformation,
pub network: NetworkInformation,
pub location: LocationInformation,
pub extended: ExtendedInformation,
}
#[derive(Deserialize, Serialize, Clone)]
struct InputJSON {
#[serde(alias = "File Hash SHA256")]
file_hash: Option<String>,
#[serde(alias = "File Modified")]
file_modified: Option<String>,
#[serde(alias = "File Path")]
file_path: Option<String>,
#[serde(alias = "SafetyCheck Timestamp")]
safety_check_timestamp: Option<String>,
#[serde(alias = "Hardware")]
hardware: Option<String>,
#[serde(alias = "Device ID")]
device_id_1: Option<String>,
#[serde(alias = "DeviceID")]
device_id_2: Option<String>,
#[serde(alias = "Device ID Vendor")]
device_id_3: Option<String>,
#[serde(alias = "Proof Generated")]
proof_generated: Option<String>, #[serde(alias = "Locale")]
locale: Option<String>,
#[serde(alias = "Network")]
network: Option<String>,
#[serde(alias = "CellInfo")]
cell_info: Option<String>,
#[serde(alias = "Manufacturer")]
manufacturer: Option<String>,
#[serde(alias = "Location.Latitude", deserialize_with = "as_f64")]
location_latitude: f64,
#[serde(alias = "Location.Longitude", deserialize_with = "as_f64")]
location_longitude: f64,
#[serde(alias = "Location.Altitude")]
location_altitude: Option<String>,
#[serde(alias = "Location.Speed")]
location_speed: Option<String>,
#[serde(alias = "Location.Accuracy")]
location_accuracy: Option<String>,
#[serde(alias = "Location.Time")]
location_time: Option<String>,
#[serde(alias = "Location.Bearing")]
location_bearing: Option<String>,
#[serde(alias = "Location.Provider")]
location_provider: Option<String>,
#[serde(alias = "DataType")]
data_type: Option<String>,
#[serde(alias = "Language")]
language: Option<String>,
#[serde(alias = "IPv6")]
ipv6: Option<String>,
#[serde(alias = "IPv4")]
ipv4: Option<String>,
#[serde(alias = "ScreenSize")]
screen_size: Option<String>,
#[serde(alias = "NetworkType")]
network_type: Option<String>,
}
pub fn translate_to_latest_schema(json: &[u8]) -> Option<ProofModeJSON> {
let input_json: Result<InputJSON, _> = serde_json::from_slice(json);
if let Ok(input_json) = input_json {
let version = "UNKNOWN".to_string(); let _generated_at = input_json.proof_generated;
let file = FileInformation {
path: input_json.file_path,
created_at: input_json.file_modified.clone(),
modified_at: input_json.file_modified,
hash: vec![FileHash {
r#type: HashType::SHA256,
value: input_json.file_hash,
}]
.into(),
};
let device = DeviceInformation {
id: input_json
.device_id_1
.or(input_json.device_id_2.or(input_json.device_id_3)),
screen_size: input_json.screen_size,
manufacturer: input_json.manufacturer,
model: input_json.hardware,
language: input_json.language,
locale: input_json.locale,
};
let network = NetworkInformation {
network_name: None,
network_type: None,
ipv4: None,
ipv6: None,
cell_info: None,
};
let location = LocationInformation {
latitude: Some(input_json.location_latitude),
longitude: Some(input_json.location_longitude),
altitude: input_json.location_altitude,
speed: input_json.location_speed,
accuracy: input_json.location_accuracy,
time: input_json.location_time,
bearing: input_json.location_bearing,
provider: input_json.location_provider,
};
let extended = ExtendedInformation { info: None };
return Some(ProofModeJSON {
version,
file,
device,
network,
location,
extended,
});
}
None
}