Skip to content

Commit

Permalink
[feature] add 'Model::add_calendar' under 'mutable-model' feature
Browse files Browse the repository at this point in the history
  • Loading branch information
woshilapin committed Apr 2, 2021
1 parent 9c25dc6 commit a9a7c55
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ members = [

[features]
xmllint = ["proj"]
# Experimental feature, use at your own risks
mutable-model = []

[dependencies]
chrono = "0.4"
Expand Down
1 change: 1 addition & 0 deletions model-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ use transit_model::{model, objects};
mod builder;

pub use crate::builder::ModelBuilder;
pub use transit_model::objects::*;
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@
//! this case, take a look at the [`CONTRIBUTING.md`] for more information on
//! this feature.
//!
//! ## `mutable-model`
//! This is an experimental feature that allows you to get some abilities to
//! mutate a `Model`. It might not be completely stable at the moment so use
//! with care (or not at all!).
//!
//! [`CONTRIBUTING.md`]: https://github.com/CanalTP/transit_model/blob/master/CONTRIBUTING.md
#![deny(missing_docs)]
Expand Down
81 changes: 81 additions & 0 deletions src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1242,6 +1242,7 @@ impl Collections {
pub struct Model {
collections: Collections,

// WARNING: Please check all methods that takes &mut self before adding a new relation (see feature 'mutable-model')
// original relations
networks_to_lines: OneToMany<Network, Line>,
commercial_modes_to_lines: OneToMany<CommercialMode, Line>,
Expand Down Expand Up @@ -1446,6 +1447,86 @@ impl Model {
self.collections
}
}
#[cfg(feature = "mutable-model")]
impl Model {
/// Add a Calendar inside the model
pub fn add_calendar(&mut self, calendar: Calendar) -> Result<Idx<Calendar>> {
self.collections
.calendars
.push(calendar)
.map_err(|e| format_err!("{}", e))
}
/// Add a new relation between a calendar and some vehicle journeys
pub fn connect_calendar_to_vehicle_journeys(
&mut self,
calendar_idx: Idx<Calendar>,
vehicle_journey_idxs: impl IntoIterator<Item = Idx<VehicleJourney>>,
) -> Result<()> {
let calendar_id = &self.collections.calendars[calendar_idx].id;
for vehicle_journey_idx in vehicle_journey_idxs {
self.collections
.vehicle_journeys
.index_mut(vehicle_journey_idx)
.service_id = calendar_id.clone();
}
self.calendars_to_vehicle_journeys = OneToMany::new(
&self.collections.calendars,
&self.collections.vehicle_journeys,
"calendars_to_vehicle_journeys",
)?;
Ok(())
}
}

#[cfg(all(test, feature = "mutable-model"))]
mod mutable_model_tests {
use relational_types::IdxSet;
use transit_model_builder::{Calendar, VehicleJourney};

#[test]
fn test_add_calendar() {
let mut model = transit_model_builder::ModelBuilder::default()
.calendar("service1", &["2021-03-14", "2021-05-04"])
.vj("vj1", |vj| {
vj.calendar("service1")
.st("SP1", "10:00:00", "10:01:00")
.st("SP2", "11:00:00", "11:01:00");
})
.vj("vj2", |vj| {
vj.calendar("service1")
.st("SP3", "12:00:00", "12:01:00")
.st("SP4", "13:00:00", "13:01:00");
})
.build();
let service1_idx = model.calendars.get_idx("service1").unwrap();
let vj1_idx = model.vehicle_journeys.get_idx("vj1").unwrap();
let vj2_idx = model.vehicle_journeys.get_idx("vj2").unwrap();

// Add a new calendar
let service2_idx = model
.add_calendar(Calendar {
id: "service2".to_string(),
..Default::default()
})
.unwrap();
model
.connect_calendar_to_vehicle_journeys(service2_idx, vec![vj2_idx])
.unwrap();

// hat 'service2' is accessible from 'vj2'
let calendar_indexes: IdxSet<Calendar> = model.get_corresponding_from_idx(vj2_idx);
assert_eq!(*calendar_indexes.iter().next().unwrap(), service2_idx);

// hat 'vj2' is accessible from 'service2'
let vj_indexes: IdxSet<VehicleJourney> = model.get_corresponding_from_idx(service2_idx);
assert_eq!(*vj_indexes.iter().next().unwrap(), vj2_idx);

// Verify that only 'vj1' is accessible from 'service1' now ('vj2' is not anymore)
let vj_indexes: IdxSet<VehicleJourney> = model.get_corresponding_from_idx(service1_idx);
assert_eq!(*vj_indexes.iter().next().unwrap(), vj1_idx);
}
}

impl ::serde::Serialize for Model {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand Down

0 comments on commit a9a7c55

Please sign in to comment.