Skip to content
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

Mathml #8

Open
carrascomj opened this issue Nov 13, 2020 · 5 comments
Open

Mathml #8

carrascomj opened this issue Nov 13, 2020 · 5 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@carrascomj
Copy link
Owner

carrascomj commented Nov 13, 2020

In #7, MathML was removed, given that it is not trivially integrated with serde. This hampers any useful implementation of InitialAssignments, Constraints and Functions.

@carrascomj carrascomj added enhancement New feature or request help wanted Extra attention is needed labels Nov 13, 2020
@ballaneypranav
Copy link

Hey, I'm Pranav and I'm working on an SBML Simulator in Rust as part of GSoC this year.

Firstly, thanks a lot for implementing this parser! This greatly simplifies my work and I would like to contribute here so I can use it for the simulator. So I wanted to start off with MathML and I tried to make it work but like you said in #7, the mathml crate can't be used here. So I wanted to know if you have any pointers for me to start working on this. (I'm also quite new to Rust.) Would it be the right approach to migrate the MathML parser to quickxml?

@carrascomj
Copy link
Owner Author

Thanks for your interest in the projec!

That's awesome. I believe that migrating the mathml parser is the right choice. At the very least, it can provide a starting point so that you don't have to go through all the mathml documentation from scratch. Three things to notice:

  1. MathML is inherently recursive as you may have noticed (see, for instance, the MathNode enum). This requires some thinking in how to write the structs. I am not sure about what's better but If you find yourself implementing a custom Serialize/Deserialize for everything, it may be easier to rely directly on quick-xml, without the serde feature. After that, the serde traits can be implemented in your mathml parser or here, if actually needed.
  2. If you decide to go the serde route but are not familiar with it, I can recommend the fantastic serde's user guide.
  3. There is this crate that I created more or less at the same time than SBML. It is only for COBRA (just FBA and a parallel naive FVA) and there are some rough edges that I don't like about how the project is structured, but it might be an interesting read if you want to do a SBML Simulator in Rust.

Other than that, I would be happy to have MathML working here. If you needed other SBML plugins than FBC, we can think about how to best write them because they are based in an OOP hierarchy which does not feel all that well in Rust (any suggestions are welcome!).

@ballaneypranav
Copy link

ballaneypranav commented Jun 12, 2021

Thanks a lot for your suggestions! I tried using serde but I can't figure out how to write the structs. It either panics or gives a stack overflow. I also posted on SO here and it seems to be a limitation with quick-xml.

Using quick-xml without serde, would it be possible to integrate the mathml parser within rust_sbml? Because seems like serde traits are a requirement here. If they have to be implemented separately, could you give me an example?

@carrascomj
Copy link
Owner Author

My idea is that you need to implement the De/Serialize traits yourself (instead of using the derive).

/// Your struct without deriving
#[serde(rename = "math", rename_all = "camelCase")]
pub enum MathNode {
    Apply(Vec<MathNode>),
    Ci(Vec<MathNode>),
    Text(String),
    #[serde(rename = "math")]
    Root(Vec<MathNode>),
}

impl Serialize for MathNode {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            // not super sure about `serialize_vec` (it may be another name/way),
            // but it is just an example
            Self::Apply(ref vec_nodes) => serializer.serialize_vec(vec_nodes),
            Self::Text(s) => serializer.serialize_str(s),
           // etc.
        }
    }
}

If you prefer the raw quick_xml route, it would be about writing something like:

fn parse_mathml(input_note: &str) -> MathNode {
    /// this is where your quick_xml logic goes
}

fn write_mathml(input_note: &MathNode) -> String {
    /// this is where your quick_xml logic goes
}

(I haven´t looked at quick_xml in a while, so I may be quite wrong about the exact way of doing things. This should be the output anyways.)

And then your custom implementations of De/Serialize call the above functions.

One question that I have is whether it is easier to just fork the current mathml and implement the required serde traits calling the different functions there. It will run slower than quick_xml and will ultimately add more dependencies to this crate, but it should get you to a Minimum Viable Product faster, unless there was some drawback that I don't remember from when I made the change to quick_xml.

@carrascomj
Copy link
Owner Author

Some naive implementation here, with math in InitialAssigment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants