use crate::navigation_controller::{
models::TripState,
step_advance::conditions::{
AndAdvanceConditions, DistanceEntryAndExitCondition, DistanceEntryAndSnappedExitCondition,
DistanceFromStepCondition, DistanceToEndOfStepCondition, ManualStepCondition,
OrAdvanceConditions,
},
};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
#[cfg(feature = "wasm-bindgen")]
use tsify::Tsify;
pub mod conditions;
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
pub struct StepAdvanceResult {
should_advance: bool,
pub next_iteration: Arc<dyn StepAdvanceCondition>,
}
impl StepAdvanceResult {
pub fn should_advance(&self) -> bool {
self.should_advance
}
pub fn continue_with_state(next_iteration: Arc<dyn StepAdvanceCondition>) -> Self {
Self {
should_advance: false,
next_iteration,
}
}
pub fn advance_to_new_instance(condition: &dyn StepAdvanceCondition) -> Self {
Self {
should_advance: true,
next_iteration: condition.new_instance(),
}
}
}
pub trait StepAdvanceConditionSerializable {
fn to_js(&self) -> SerializableStepAdvanceCondition;
}
#[cfg_attr(feature = "uniffi", uniffi::export)]
pub trait StepAdvanceCondition: StepAdvanceConditionSerializable + Sync + Send {
fn should_advance_step(&self, trip_state: TripState) -> StepAdvanceResult;
fn new_instance(&self) -> Arc<dyn StepAdvanceCondition>;
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
#[cfg_attr(feature = "wasm-bindgen", derive(Tsify))]
#[cfg_attr(feature = "wasm-bindgen", tsify(from_wasm_abi))]
pub enum SerializableStepAdvanceCondition {
Manual,
#[cfg_attr(feature = "wasm-bindgen", serde(rename_all = "camelCase"))]
DistanceToEndOfStep {
distance: u16,
minimum_horizontal_accuracy: u16,
},
#[cfg_attr(feature = "wasm-bindgen", serde(rename_all = "camelCase"))]
DistanceFromStep {
distance: u16,
minimum_horizontal_accuracy: u16,
calculate_while_off_route: bool,
},
#[cfg_attr(feature = "wasm-bindgen", serde(rename_all = "camelCase"))]
DistanceEntryExit {
distance_to_end_of_step: u16,
distance_after_end_step: u16,
minimum_horizontal_accuracy: u16,
has_reached_end_of_current_step: bool,
},
#[cfg_attr(feature = "wasm-bindgen", serde(rename_all = "camelCase"))]
DistanceEntryAndSnappedExit {
distance_to_end_of_step: u16,
distance_after_end_step: u16,
minimum_horizontal_accuracy: u16,
has_reached_end_of_current_step: bool,
},
#[cfg_attr(feature = "wasm-bindgen", serde(rename_all = "camelCase"))]
OrAdvanceConditions {
conditions: Vec<SerializableStepAdvanceCondition>,
},
#[cfg_attr(feature = "wasm-bindgen", serde(rename_all = "camelCase"))]
AndAdvanceConditions {
conditions: Vec<SerializableStepAdvanceCondition>,
},
}
impl From<SerializableStepAdvanceCondition> for Arc<dyn StepAdvanceCondition> {
fn from(condition: SerializableStepAdvanceCondition) -> Arc<dyn StepAdvanceCondition> {
match condition {
SerializableStepAdvanceCondition::Manual => Arc::new(ManualStepCondition),
SerializableStepAdvanceCondition::DistanceToEndOfStep {
distance,
minimum_horizontal_accuracy,
} => Arc::new(DistanceToEndOfStepCondition {
distance,
minimum_horizontal_accuracy,
}),
SerializableStepAdvanceCondition::DistanceFromStep {
distance,
minimum_horizontal_accuracy,
calculate_while_off_route,
} => Arc::new(DistanceFromStepCondition {
distance,
minimum_horizontal_accuracy,
calculate_while_off_route,
}),
SerializableStepAdvanceCondition::DistanceEntryExit {
minimum_horizontal_accuracy,
distance_to_end_of_step,
distance_after_end_step,
has_reached_end_of_current_step,
} => Arc::new(DistanceEntryAndExitCondition {
minimum_horizontal_accuracy,
distance_to_end_of_step,
distance_after_end_of_step: distance_after_end_step,
has_reached_end_of_current_step,
}),
SerializableStepAdvanceCondition::DistanceEntryAndSnappedExit {
minimum_horizontal_accuracy,
distance_to_end_of_step,
distance_after_end_step,
has_reached_end_of_current_step,
} => Arc::new(DistanceEntryAndSnappedExitCondition {
minimum_horizontal_accuracy,
distance_to_end_of_step,
distance_after_end_of_step: distance_after_end_step,
has_reached_end_of_current_step,
}),
SerializableStepAdvanceCondition::OrAdvanceConditions { conditions } => {
Arc::new(OrAdvanceConditions {
conditions: conditions.into_iter().map(Into::into).collect(),
})
}
SerializableStepAdvanceCondition::AndAdvanceConditions { conditions } => {
Arc::new(AndAdvanceConditions {
conditions: conditions.into_iter().map(Into::into).collect(),
})
}
}
}
}
#[cfg(feature = "uniffi")]
#[uniffi::export]
pub fn step_advance_manual() -> Arc<dyn StepAdvanceCondition> {
Arc::new(ManualStepCondition)
}
#[cfg(feature = "uniffi")]
#[uniffi::export]
pub fn step_advance_distance_to_end_of_step(
distance: u16,
minimum_horizontal_accuracy: u16,
) -> Arc<dyn StepAdvanceCondition> {
Arc::new(DistanceToEndOfStepCondition {
distance,
minimum_horizontal_accuracy,
})
}
#[cfg(feature = "uniffi")]
#[uniffi::export]
pub fn step_advance_distance_from_step(
distance: u16,
minimum_horizontal_accuracy: u16,
calculate_while_off_route: bool,
) -> Arc<dyn StepAdvanceCondition> {
Arc::new(DistanceFromStepCondition {
distance,
minimum_horizontal_accuracy,
calculate_while_off_route,
})
}
#[cfg(feature = "uniffi")]
#[uniffi::export]
pub fn step_advance_or(
conditions: Vec<Arc<dyn StepAdvanceCondition>>,
) -> Arc<dyn StepAdvanceCondition> {
Arc::new(OrAdvanceConditions { conditions })
}
#[cfg(feature = "uniffi")]
#[uniffi::export]
pub fn step_advance_and(
conditions: Vec<Arc<dyn StepAdvanceCondition>>,
) -> Arc<dyn StepAdvanceCondition> {
Arc::new(AndAdvanceConditions { conditions })
}
#[cfg(feature = "uniffi")]
#[uniffi::export]
pub fn step_advance_distance_entry_and_exit(
distance_to_end_of_step: u16,
distance_after_end_of_step: u16,
minimum_horizontal_accuracy: u16,
) -> Arc<dyn StepAdvanceCondition> {
Arc::new(DistanceEntryAndExitCondition {
distance_to_end_of_step,
distance_after_end_of_step,
minimum_horizontal_accuracy,
has_reached_end_of_current_step: false,
})
}
#[cfg(feature = "uniffi")]
#[uniffi::export]
pub fn step_advance_distance_entry_and_snapped_exit(
distance_to_end_of_step: u16,
distance_after_end_of_step: u16,
minimum_horizontal_accuracy: u16,
) -> Arc<dyn StepAdvanceCondition> {
Arc::new(DistanceEntryAndSnappedExitCondition {
distance_to_end_of_step,
distance_after_end_of_step,
minimum_horizontal_accuracy,
has_reached_end_of_current_step: false,
})
}