use chrono::Utc;
use serde::{Deserialize, Serialize};
use crate::{
models::Route,
navigation_controller::{
models::{
NavigationControllerConfig, SerializableNavState,
SerializableNavigationControllerConfig, TripState,
},
step_advance::SerializableStepAdvanceCondition,
},
};
#[cfg(feature = "wasm-bindgen")]
use tsify::Tsify;
#[derive(Serialize, Deserialize, Clone)]
pub struct NavigationRecordingMetadata {
pub version: String,
pub initial_timestamp: i64,
pub config: SerializableNavigationControllerConfig,
pub initial_route: Route,
}
impl NavigationRecordingMetadata {
pub fn new(config: NavigationControllerConfig, initial_route: Route) -> Self {
Self {
version: env!("CARGO_PKG_VERSION").to_string(),
initial_timestamp: Utc::now().timestamp_millis(),
config: SerializableNavigationControllerConfig::from(config),
initial_route,
}
}
pub fn to_json(&self, events: Vec<NavigationRecordingEvent>) -> Result<String, RecordingError> {
let recording = NavigationRecording {
recording: self.clone(),
events,
};
serde_json::to_string(&recording).map_err(|e| RecordingError::SerializationError {
error: e.to_string(),
})
}
}
#[derive(Serialize, Deserialize, Clone)]
pub struct NavigationRecording {
#[serde(flatten)]
pub recording: NavigationRecordingMetadata,
pub events: Vec<NavigationRecordingEvent>,
}
impl NavigationRecording {
pub fn from_json(json: &str) -> Self {
serde_json::from_str(json)
.map_err(|e| RecordingError::SerializationError {
error: e.to_string(),
})
.unwrap()
}
}
#[derive(Debug, Serialize, thiserror::Error)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Error))]
pub enum RecordingError {
#[error("Error serializing navigation recording: {error}.")]
SerializationError { error: String },
#[error("Recording is not enabled for this controller.")]
RecordingNotEnabled,
}
#[derive(Clone, Serialize, Deserialize, Debug)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
#[cfg_attr(feature = "wasm-bindgen", derive(Tsify))]
pub struct NavigationRecordingEvent {
pub timestamp: i64,
pub event_data: NavigationRecordingEventData,
}
impl NavigationRecordingEvent {
pub fn new(event_data: NavigationRecordingEventData) -> Self {
Self {
timestamp: Utc::now().timestamp_millis(),
event_data,
}
}
pub fn state_update(serializable_nav_state: SerializableNavState) -> Self {
Self::new(NavigationRecordingEventData::StateUpdate {
trip_state: serializable_nav_state.trip_state,
step_advance_condition: serializable_nav_state.step_advance_condition,
})
}
pub fn timestamp(&self) -> i64 {
self.timestamp
}
}
#[derive(Clone, Serialize, Deserialize, Debug)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
#[cfg_attr(feature = "wasm-bindgen", derive(Tsify))]
pub enum NavigationRecordingEventData {
StateUpdate {
trip_state: TripState,
step_advance_condition: SerializableStepAdvanceCondition,
},
RouteUpdate {
route: Route,
},
}