#Forced to do object-oriented classes in Rust - best way to go forward?

31 messages · Page 1 of 1 (latest)

quartz jacinth
#

Hello everyone! I'm currently busy writing an XML parsing and XSD code generation library in rust. I've gotten most features working however I'm now left with trying to add "substitution groups". Substitution groups (SGs from here) are groups of elements which can replace an existing element in a parent schema. In essence, you can think of it as a declaration of a subclass further down the chain.

Now, statically, this is simple by simply creating an enum of all known child elements that can substitute a specific parent element.

The problem becomes when you need this done dynamically - static typing no longer applies - you can take any data possible. In essence, sub-typing/class inheritance without any knowledge of it at compile time (this needs to be dynamic at runtime since the child schemas in this case need to be dynamic).

Basically what I'm trying to say is that this isn't a simple case, as far as I see I can't write it the rust way.

The options I see before me are:

  • I have to do something like OOP
  • Keeping the data in some kind of Box<dyn ...>
  • Detecting a sub-class and keeping the data unserialized

Any ideas?

#

Forced to do object-oriented classes in Rust - best way to go forward?

modern bolt
#

In this case you could use a HashMap (if I'm not wrong here), since subtituion groups basically have fields, so you can represent a number of fields with a HashMap like

HashMap<String, BaseXMLType> or similar

quartz jacinth
#
struct A {
   b: B,
   c: C,
}

struct B ...
struct C ...
modern bolt
quartz jacinth
#

now later dynamically one could declare that B can be replaced by another type

modern bolt
#

Is this XML types we are talking about or like parsing types

quartz jacinth
#

Let me show send you a link, 1 sec

#

How familiar are you with XSD?

modern bolt
#

let's say:

<xs:element name="animal" type="AnimalType" abstract="true"/>
<xs:element name="dog" substitutionGroup="animal" type="DogType"/>

which is equivalent to:

trait Animal {
    fn name(&self) -> &str;
}

struct Dog {
    name: String,
    breed: String,
}
impl Animal for Dog { ... }

therefore you could represent the fields of these with a

Vec<String>

and entries with a object with a HashMap<FieldName, XmlValue>

modern bolt
quartz jacinth
#

XSD is XML

#

XSD/XML schema

#

XSD I think is actually XML Schema Declaration

#

I say XSD sloppily

#

mb

#
#[derive(
    ::core::fmt::Debug,
    ::xmlity::Serialize,
    ::xmlity::Deserialize,
    ::bon::Builder,
    ::core::cmp::PartialEq,
    ::core::clone::Clone
)]
#[xelement(
    name = "defaultOpenContent",
    namespace = "http://www.w3.org/2001/XMLSchema",
    allow_unknown_attributes = "any",
    children_order = "strict"
)]
pub struct DefaultOpenContent {
    #[xattribute(name = "id", optional)]
    pub id: ::core::option::Option<String>,
    #[xattribute(name = "appliesToEmpty", optional)]
    pub applies_to_empty: ::core::option::Option<bool>,
    #[xattribute(name = "mode", optional)]
    pub mode: ::core::option::Option<default_open_content_items::ModeValue>,
    #[xvalue(default)]
    pub annotation: ::core::option::Option<crate::Annotation>,
    #[xelement(name = "any", namespace = "http://www.w3.org/2001/XMLSchema", group)]
    pub any: ::std::boxed::Box<crate::types::Wildcard>,
}
#

This is what gets generated

modern bolt
#

ah well if you are talking about those complexType, I just suggested representing fields as a Vev<(String, XSDValue)> for fields required

quartz jacinth
#

Now imagine I have a child substitution group that I need to accept dynamically that could look way different

modern bolt
#

damn bro

#

I haven't done this

quartz jacinth
modern bolt
#

sorry gng

#

can't help you on this one

#

good luck

quartz jacinth
#

Fair, thank for the try!

modern bolt
winter basalt
#

I would definitely just try to replace all the objects with some Object type that holds a string naming the type and a hash map containing the fields. This is how scripting languages like Python/JavaScript/Lua represent data.