proofmode 0.9.0

Capture, share, and preserve verifiable photos and videos
Documentation
use serde::{Deserialize, Serialize};
use serde_json::Value;
use serde_this_or_that::as_f64;

// const SCHEMA_VERSION: &str = "2.0.0";

#[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>, // time
    #[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(); // input_json.version.or("UNKNOWN");
        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
}