Skip to content

Provide IntoId trait for ID extraction #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions examples/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let ethanol = model
.build_species("ethanol")
.name("Ethanol")
.compartment(&compartment.id())
.compartment(&compartment)
.initial_concentration(0.5)
.unit(&mole.id())
.has_only_substance_units(false)
Expand All @@ -38,7 +38,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let aldehyde = model
.build_species("aldehyde")
.name("Aldehyde")
.compartment(&compartment.id())
.compartment(&compartment)
.initial_concentration(0.5)
.unit(&mole.id())
.has_only_substance_units(false)
Expand All @@ -48,8 +48,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
model
.build_reaction("reaction")
.name("Reaction")
.reactant(&ethanol.id(), 1.0)
.product(&aldehyde.id(), 1.0)
.reactant(&ethanol, 1.0)
.product(&aldehyde, 1.0)
.build();

// Serialize the document to an SBML string
Expand Down
5 changes: 4 additions & 1 deletion src/compartment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use std::{cell::RefCell, pin::Pin, rc::Rc};
use autocxx::c_uint;
use cxx::let_cxx_string;

use crate::{inner, model::Model, pin_ptr, sbmlcxx, sbo_term, upcast_annotation};
use crate::{inner, into_id, model::Model, pin_ptr, sbmlcxx, sbo_term, upcast_annotation};

/// A safe wrapper around the libSBML Compartment class.
///
Expand All @@ -30,6 +30,9 @@ inner!(sbmlcxx::Compartment, Compartment<'a>);
// Set the annotation trait for the Compartment struct
upcast_annotation!(Compartment<'a>, sbmlcxx::Compartment, sbmlcxx::SBase);

// Set the into_id trait for the Compartment struct
into_id!(&Rc<Compartment<'_>>, id);

impl<'a> Compartment<'a> {
/// Creates a new Compartment instance within the given Model.
///
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub mod traits {
pub mod annotation;
pub mod fromptr;
pub mod inner;
pub mod intoid;
}

/// Module providing upcast functionality
Expand Down Expand Up @@ -77,6 +78,7 @@ pub mod prelude {
pub use crate::species::*;
pub use crate::speciesref::*;
pub use crate::traits::annotation::*;
pub use crate::traits::intoid::*;
pub use crate::unit::*;
pub use crate::unitdef::*;
}
Expand Down
11 changes: 11 additions & 0 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,3 +253,14 @@ macro_rules! sbo_term {
}
};
}

#[macro_export]
macro_rules! into_id {
($type:ty, $property:ident) => {
impl<'a> crate::traits::intoid::IntoId<'a> for $type {
fn into_id(self) -> &'a str {
Box::leak(self.$property().into_boxed_str())
}
}
};
}
7 changes: 4 additions & 3 deletions src/modref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
use std::{cell::RefCell, pin::Pin};

use crate::{
inner, pin_ptr, reaction::Reaction, sbmlcxx, sbo_term, upcast, upcast_annotation, upcast_pin,
inner, pin_ptr, prelude::IntoId, reaction::Reaction, sbmlcxx, sbo_term, upcast,
upcast_annotation, upcast_pin,
};
use cxx::let_cxx_string;

Expand Down Expand Up @@ -115,8 +116,8 @@ impl<'a> ModifierSpeciesReferenceBuilder<'a> {
///
/// # Returns
/// A new ModifierSpeciesReferenceBuilder instance
pub fn new(reaction: &Reaction<'a>, sid: &str) -> Self {
let modifier_reference = ModifierSpeciesReference::new(reaction, sid);
pub fn new(reaction: &Reaction<'a>, sid: impl IntoId<'a>) -> Self {
let modifier_reference = ModifierSpeciesReference::new(reaction, sid.into_id());
Self { modifier_reference }
}

Expand Down
5 changes: 4 additions & 1 deletion src/parameter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use std::{cell::RefCell, pin::Pin, rc::Rc};
use cxx::let_cxx_string;

use crate::{
inner,
inner, into_id,
model::Model,
pin_ptr,
sbmlcxx::{self},
Expand All @@ -36,6 +36,9 @@ inner!(sbmlcxx::Parameter, Parameter<'a>);
// Set the annotation trait for the Parameter struct
upcast_annotation!(Parameter<'a>, sbmlcxx::Parameter, sbmlcxx::SBase);

// Set the into_id trait for the Compartment struct
into_id!(&Rc<Parameter<'_>>, id);

impl<'a> Parameter<'a> {
/// Creates a new Parameter instance within the given Model.
///
Expand Down
37 changes: 25 additions & 12 deletions src/reaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ use std::{cell::RefCell, pin::Pin, rc::Rc};
use cxx::let_cxx_string;

use crate::{
inner,
inner, into_id,
model::Model,
modref::{ModifierSpeciesReference, ModifierSpeciesReferenceBuilder},
pin_ptr,
prelude::IntoId,
sbmlcxx::{self},
sbo_term,
speciesref::{SpeciesReference, SpeciesReferenceBuilder, SpeciesReferenceType},
Expand All @@ -42,6 +43,9 @@ inner!(sbmlcxx::Reaction, Reaction<'a>);
// Set the annotation trait for the Reaction struct
upcast_annotation!(Reaction<'a>, sbmlcxx::Reaction, sbmlcxx::SBase);

// Set the into_id trait for the Reaction struct
into_id!(&Rc<Reaction<'_>>, id);

impl<'a> Reaction<'a> {
/// Creates a new Reaction instance within the given Model.
///
Expand Down Expand Up @@ -116,7 +120,11 @@ impl<'a> Reaction<'a> {
///
/// # Returns
/// A reference-counted pointer to the new SpeciesReference
pub fn create_product(&self, sid: &str, stoichiometry: f64) -> Rc<SpeciesReference<'a>> {
pub fn create_product(
&self,
sid: impl IntoId<'a>,
stoichiometry: f64,
) -> Rc<SpeciesReference<'a>> {
let product = Rc::new(SpeciesReference::new(
self,
sid,
Expand All @@ -134,7 +142,7 @@ impl<'a> Reaction<'a> {
///
/// # Returns
/// A SpeciesReferenceBuilder for configuring and creating the product
pub fn build_product(&self, sid: &str) -> SpeciesReferenceBuilder<'a> {
pub fn build_product(&self, sid: impl IntoId<'a>) -> SpeciesReferenceBuilder<'a> {
SpeciesReferenceBuilder::new(&self, sid, SpeciesReferenceType::Product)
}

Expand Down Expand Up @@ -169,7 +177,11 @@ impl<'a> Reaction<'a> {
///
/// # Returns
/// A reference-counted pointer to the new SpeciesReference
pub fn create_reactant(&self, sid: &str, stoichiometry: f64) -> Rc<SpeciesReference<'a>> {
pub fn create_reactant(
&self,
sid: impl IntoId<'a>,
stoichiometry: f64,
) -> Rc<SpeciesReference<'a>> {
let reactant = Rc::new(SpeciesReference::new(
self,
sid,
Expand All @@ -187,7 +199,7 @@ impl<'a> Reaction<'a> {
///
/// # Returns
/// A SpeciesReferenceBuilder for configuring and creating the reactant
pub fn build_reactant(&self, sid: &str) -> SpeciesReferenceBuilder<'a> {
pub fn build_reactant(&self, sid: impl IntoId<'a>) -> SpeciesReferenceBuilder<'a> {
SpeciesReferenceBuilder::new(&self, sid, SpeciesReferenceType::Reactant)
}

Expand Down Expand Up @@ -234,7 +246,7 @@ impl<'a> Reaction<'a> {
///
/// # Returns
/// A ModifierSpeciesReferenceBuilder for configuring and creating the modifier
pub fn build_modifier(&self, sid: &str) -> ModifierSpeciesReferenceBuilder<'a> {
pub fn build_modifier(&self, sid: impl IntoId<'a>) -> ModifierSpeciesReferenceBuilder<'a> {
ModifierSpeciesReferenceBuilder::new(&self, sid)
}
/// Returns a reference to the modifiers of this reaction.
Expand Down Expand Up @@ -324,8 +336,8 @@ impl<'a> ReactionBuilder<'a> {
///
/// # Returns
/// The builder instance for method chaining
pub fn product(self, sid: &str, stoichiometry: f64) -> Self {
self.reaction.create_product(sid, stoichiometry);
pub fn product(self, sid: impl IntoId<'a>, stoichiometry: f64) -> Self {
self.reaction.create_product(sid.into_id(), stoichiometry);
self
}

Expand All @@ -337,8 +349,8 @@ impl<'a> ReactionBuilder<'a> {
///
/// # Returns
/// The builder instance for method chaining
pub fn reactant(self, sid: &str, stoichiometry: f64) -> Self {
self.reaction.create_reactant(sid, stoichiometry);
pub fn reactant(self, sid: impl IntoId<'a>, stoichiometry: f64) -> Self {
self.reaction.create_reactant(sid.into_id(), stoichiometry);
self
}

Expand All @@ -349,10 +361,11 @@ impl<'a> ReactionBuilder<'a> {
///
/// # Returns
/// The builder instance for method chaining
pub fn modifier(self, sid: &str) -> Self {
self.reaction.create_modifier(sid);
pub fn modifier(self, sid: impl IntoId<'a>) -> Self {
self.reaction.create_modifier(sid.into_id());
self
}

pub fn build(self) -> Rc<Reaction<'a>> {
self.reaction
}
Expand Down
11 changes: 8 additions & 3 deletions src/species.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ use std::{cell::RefCell, pin::Pin, rc::Rc};
use cxx::let_cxx_string;

use crate::{
inner,
inner, into_id,
model::Model,
pin_ptr,
prelude::IntoId,
sbmlcxx::{self},
sbo_term,
traits::fromptr::FromPtr,
Expand All @@ -36,6 +37,9 @@ inner!(sbmlcxx::Species, Species<'a>);
// Set the annotation trait for the Species struct
upcast_annotation!(Species<'a>, sbmlcxx::Species, sbmlcxx::SBase);

// Set the into_id trait for the Species struct
into_id!(&Rc<Species<'_>>, id);

impl<'a> Species<'a> {
/// Creates a new Species instance within the given Model.
///
Expand Down Expand Up @@ -120,7 +124,8 @@ impl<'a> Species<'a> {
///
/// # Arguments
/// * `compartment` - The identifier of the compartment
pub fn set_compartment(&self, compartment: &str) {
pub fn set_compartment(&self, compartment: impl IntoId<'a>) {
let compartment = compartment.into_id();
let_cxx_string!(compartment = compartment);
self.inner
.borrow_mut()
Expand Down Expand Up @@ -311,7 +316,7 @@ impl<'a> SpeciesBuilder<'a> {
///
/// # Arguments
/// * `compartment` - The compartment identifier
pub fn compartment(self, compartment: &str) -> Self {
pub fn compartment(self, compartment: impl IntoId<'a>) -> Self {
self.species.set_compartment(compartment);
self
}
Expand Down
23 changes: 16 additions & 7 deletions src/speciesref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use std::{cell::RefCell, pin::Pin, rc::Rc};

use crate::{
inner, pin_ptr,
prelude::IntoId,
reaction::Reaction,
sbmlcxx::{self},
sbo_term,
Expand Down Expand Up @@ -46,7 +47,11 @@ impl<'a> SpeciesReference<'a> {
///
/// # Returns
/// A new SpeciesReference instance
pub(crate) fn new(reaction: &Reaction<'a>, sid: &str, ref_type: SpeciesReferenceType) -> Self {
pub(crate) fn new(
reaction: &Reaction<'a>,
sid: impl IntoId<'a>,
ref_type: SpeciesReferenceType,
) -> Self {
let species_reference_ptr = match ref_type {
SpeciesReferenceType::Reactant => {
reaction.inner().borrow_mut().as_mut().createReactant()
Expand All @@ -60,7 +65,7 @@ impl<'a> SpeciesReference<'a> {
// We need to fall back to custom wrappers for the species reference
// because autocxx does not support setting the species reference's species
// most likely because it is a virtual base class.
let_cxx_string!(sid = sid);
let_cxx_string!(sid = sid.into_id());
let simple_spec_ref = upcast_pin!(
species_reference,
sbmlcxx::SpeciesReference,
Expand Down Expand Up @@ -98,14 +103,14 @@ impl<'a> SpeciesReference<'a> {
///
/// # Arguments
/// * `species` - The species to set
pub fn set_species(&self, species: &str) {
pub fn set_species(&self, species: impl IntoId<'a>) {
let simple_spec_ref = upcast!(
self,
sbmlcxx::SpeciesReference,
sbmlcxx::SimpleSpeciesReference
);

let_cxx_string!(species = species);
let_cxx_string!(species = species.into_id());
simple_spec_ref.setSpecies(&species);
}

Expand Down Expand Up @@ -193,10 +198,14 @@ impl<'a> SpeciesReferenceBuilder<'a> {
///
/// # Returns
/// A new SpeciesReferenceBuilder instance
pub fn new(reaction: &Reaction<'a>, sid: &str, ref_type: SpeciesReferenceType) -> Self {
pub fn new(
reaction: &Reaction<'a>,
sid: impl IntoId<'a>,
ref_type: SpeciesReferenceType,
) -> Self {
let species_reference = match ref_type {
SpeciesReferenceType::Reactant => reaction.create_reactant(sid, 1.0),
SpeciesReferenceType::Product => reaction.create_product(sid, 1.0),
SpeciesReferenceType::Reactant => reaction.create_reactant(sid.into_id(), 1.0),
SpeciesReferenceType::Product => reaction.create_product(sid.into_id(), 1.0),
};

Self { species_reference }
Expand Down
Loading