use smallvec::SmallVec;
use crate::ids::StopIdx;
use crate::time::Duration;
#[derive(Debug, Clone, Default)]
pub struct Endpoints {
stops: SmallVec<[(StopIdx, Duration); 50]>,
}
impl Endpoints {
pub fn new() -> Self {
Self::default()
}
pub fn len(&self) -> usize {
self.stops.len()
}
pub fn is_empty(&self) -> bool {
self.stops.is_empty()
}
pub fn as_slice(&self) -> &[(StopIdx, Duration)] {
&self.stops
}
pub fn push(&mut self, stop: StopIdx, walk: Duration) {
self.stops.push((stop, walk));
}
pub fn from_stop_indices(stops: &[u32]) -> Self {
let mut e = Self::new();
for &s in stops {
e.push(StopIdx::new(s), Duration::ZERO);
}
e
}
pub fn from_pairs(pairs: &[(u32, u32)]) -> Self {
let mut e = Self::new();
for &(s, w) in pairs {
e.push(StopIdx::new(s), Duration(w));
}
e
}
}
pub trait IntoEndpoints {
fn into_endpoints(self) -> Endpoints;
}
impl IntoEndpoints for StopIdx {
fn into_endpoints(self) -> Endpoints {
let mut e = Endpoints::new();
e.push(self, Duration::ZERO);
e
}
}
impl IntoEndpoints for (StopIdx, Duration) {
fn into_endpoints(self) -> Endpoints {
let mut e = Endpoints::new();
e.push(self.0, self.1);
e
}
}
impl IntoEndpoints for &[StopIdx] {
fn into_endpoints(self) -> Endpoints {
let mut e = Endpoints::new();
for &s in self {
e.push(s, Duration::ZERO);
}
e
}
}
impl<const N: usize> IntoEndpoints for &[StopIdx; N] {
fn into_endpoints(self) -> Endpoints {
(self.as_slice()).into_endpoints()
}
}
impl IntoEndpoints for &[(StopIdx, Duration)] {
fn into_endpoints(self) -> Endpoints {
let mut e = Endpoints::new();
for &p in self {
e.push(p.0, p.1);
}
e
}
}
impl<const N: usize> IntoEndpoints for &[(StopIdx, Duration); N] {
fn into_endpoints(self) -> Endpoints {
(self.as_slice()).into_endpoints()
}
}
impl IntoEndpoints for Vec<StopIdx> {
fn into_endpoints(self) -> Endpoints {
(self.as_slice()).into_endpoints()
}
}
impl IntoEndpoints for &Vec<StopIdx> {
fn into_endpoints(self) -> Endpoints {
(self.as_slice()).into_endpoints()
}
}
impl IntoEndpoints for Vec<(StopIdx, Duration)> {
fn into_endpoints(self) -> Endpoints {
let mut e = Endpoints::new();
for p in self {
e.push(p.0, p.1);
}
e
}
}
impl IntoEndpoints for &Vec<(StopIdx, Duration)> {
fn into_endpoints(self) -> Endpoints {
(self.as_slice()).into_endpoints()
}
}
impl IntoEndpoints for &Endpoints {
fn into_endpoints(self) -> Endpoints {
self.clone()
}
}
impl IntoEndpoints for Endpoints {
fn into_endpoints(self) -> Endpoints {
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn from_stop_indices_assigns_zero_walk() {
let e = Endpoints::from_stop_indices(&[3, 7, 11]);
assert_eq!(e.len(), 3);
let pairs: Vec<_> = e.as_slice().to_vec();
assert_eq!(pairs[0], (StopIdx::new(3), Duration::ZERO));
assert_eq!(pairs[1], (StopIdx::new(7), Duration::ZERO));
assert_eq!(pairs[2], (StopIdx::new(11), Duration::ZERO));
}
#[test]
fn from_pairs_preserves_walk_offsets() {
let e = Endpoints::from_pairs(&[(0, 0), (5, 60), (12, 240)]);
assert_eq!(e.len(), 3);
let pairs: Vec<_> = e.as_slice().to_vec();
assert_eq!(pairs[0], (StopIdx::new(0), Duration(0)));
assert_eq!(pairs[1], (StopIdx::new(5), Duration(60)));
assert_eq!(pairs[2], (StopIdx::new(12), Duration(240)));
}
#[test]
fn from_stop_indices_empty_slice() {
let e = Endpoints::from_stop_indices(&[]);
assert!(e.is_empty());
}
}