Advice on how to structure a project

This is my first Rust project, and I am unsure of how to build my core program structure. Especially the part of storing and fetching data (from memory).

My scenario is this:
I get packages on different topics (MQTT). And the "definition" payloads looks like this:

{
    "name": "my/first/metric"
    "timestamp": 1486144502122,
    "datatype": "Float",
    "properties": {
        "quality": {
            "datatype": "Int",
            "value": 192
        },
        "engineering units": {
            "datatype": "String",
            "value": "kw/h"
        }
    }
}

Based on the "definition" payload(s) i am going to populate my Metric "storage structure", which currently is Structure based.

Then some time in the very close future after starting the program, i might be getting different payloads on other topics. These are the actual values coming to update the internal metric structure. Some values might never come though, meaning they will be None forever. These "normal" payloads look like this:

{
    "name": "my/first/metric"
    "timestamp": 1486144502122,
    "value": 13.38
}

*Sidenote: I have abstracted away some encoding and aliasing here. *

In the end i would love to have my storage structure in a hashmap, with all metric names as keys, and values would hold the Metric structure itself.

The dream is for me to this when i run my callbacks:

my_hashmap[incoming_value["name"]].update_value( incoming_value["value"] )

or

my_hashmap["my/first/metric"].get_value( )

Sidenote, if curious there exist a thread were the current solution can be viewed. Here is the thread where I tried to create this structure by myself:

I am not sure what the question is. I see you have tried to break it down as well as you could but it is not clear to me still.

If your metric payload data structure is determined by the metric ID, and you want to store those metric payloads as a single type, you will need to use an enum where the variants hold the diffent kinds of payload data. This was suggested in your previous post. To deserialize the data, you could look at Enum representations · Serde.

2 Likes

If a metric has multiple properties, the above is not enough info to update it -- there is no property name.

EDIT: Or does a metric have a single "main" data type, which is the type of all incoming values?

Please explain the meaning of datatype and timestamp above, and their relationship to the fields in the incoming payloads.

Thanks for the support guys. As suggested both here and in the another thread, I went for the Enum variant to store my data.

In order to store the values in the correct enum::"Type", i used a separate field for identifying the datatype, and i then initialize the valuefield struct using f.ex None::<i32>.

Later in order to have a common function fn update_value<T>(val:T), to be used for updating all values, i created a trait cast_any, and implement at this on the used primitive datatypes

I'd be happy to do a review with you of the code, if you're open to a pair programming session. Find me through Mick van Gelderen - Volkswagen AG | LinkedIn.

2 Likes