Skip to content

Commit

Permalink
refactor: Use generics to improve builder ergonomics
Browse files Browse the repository at this point in the history
* improve doc tests
  • Loading branch information
molpopgen committed Sep 18, 2023
1 parent 0308844 commit c085cc3
Showing 1 changed file with 54 additions and 8 deletions.
62 changes: 54 additions & 8 deletions demes/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,24 @@ pub struct GraphBuilder {
/// # Examples
///
/// See [`GraphBuilder::add_migration`].
///
/// # Notes
///
/// A default (empty) instance must specify the generic types:
///
/// ```
/// let _ = demes::SymmetricMigrationBuilder::<String, &[String]>::default();
/// ```
/// ```
/// let _ = demes::SymmetricMigrationBuilder::<&str, &[&str]>::default();
/// ```
///
/// Similarly, an instance not specifying `demes`
/// specify the generic type:
///
/// ```
/// let _ = demes::SymmetricMigrationBuilder::<&str, &[&str]>{rate: Some(0.1.into()), ..Default::default()};
/// ````
#[derive(Clone, Default)]
pub struct SymmetricMigrationBuilder<A: AsRef<str>, S: std::ops::Deref<Target = [A]>> {
/// The demes that are involved
Expand Down Expand Up @@ -75,6 +93,24 @@ impl<A: AsRef<str>, D: std::ops::Deref<Target = [A]>> From<SymmetricMigrationBui
}

/// Build an asymmetric migration epoch.
///
/// # Notes
///
/// A default (empty) instance must specify the generic types:
///
/// ```
/// let _ = demes::AsymmetricMigrationBuilder::<&str>::default();
/// ```
/// ```
/// let _ = demes::AsymmetricMigrationBuilder::<String>::default();
/// ```
///
/// Similarly, an instance not specifying `source` nor `dest` must also
/// specify the generic type:
///
/// ```
/// let _ = demes::AsymmetricMigrationBuilder::<&str>{rate: Some(0.1.into()), ..Default::default()};
/// ````
#[derive(Clone, Default)]
pub struct AsymmetricMigrationBuilder<A: AsRef<str>> {
/// The source deme
Expand Down Expand Up @@ -146,14 +182,14 @@ impl GraphBuilder {
/// ```
///
/// # Notes
pub fn add_deme(
pub fn add_deme<D: std::ops::Deref<Target = [UnresolvedEpoch]>>(
&mut self,
name: &str,
epochs: Vec<UnresolvedEpoch>,
epochs: D,
history: UnresolvedDemeHistory,
description: Option<&str>,
) {
let ptr = UnresolvedDeme::new_via_builder(name, epochs, history, description);
let ptr = UnresolvedDeme::new_via_builder(name, epochs.to_owned(), history, description);
self.graph.add_deme(ptr);
}

Expand Down Expand Up @@ -236,19 +272,29 @@ impl GraphBuilder {
/// b.add_deme("B", vec![epoch], history, Some("this is deme B"));
/// b.add_pulse(Some(&["A"]),
/// Some("B"),
/// Some(demes::InputTime::from(50.0)),
/// Some(vec![demes::InputProportion::from(0.5)]));
/// Some(50.0),
/// Some([0.5].as_slice()));
/// b.resolve().unwrap();
/// ```
pub fn add_pulse(
pub fn add_pulse<
T: Into<InputTime>,
P: Into<InputProportion> + Copy,
D: std::ops::Deref<Target = [P]>,
>(
&mut self,
sources: Option<&[&str]>,
dest: Option<&str>,
time: Option<InputTime>,
proportions: Option<Vec<InputProportion>>,
time: Option<T>,
proportions: Option<D>,
) {
let sources = sources.map(|value| value.iter().map(|v| v.to_string()).collect::<Vec<_>>());
let dest = dest.map(|value| value.to_string());
let time = time.map(|t| t.into());
let proportions = proportions.map(|s| {
s.iter()
.map(|p| (*p).into())
.collect::<Vec<InputProportion>>()
});
self.graph.add_pulse(sources, dest, time, proportions);
}

Expand Down

0 comments on commit c085cc3

Please sign in to comment.