1

I am a newbie and having an issues with my program. Trying to write a simple backend program which communicates with mqtt broker and does some crude operations into database.

I am getting the compiler error below and I honestly not sure what it is about.

error: to use a constant of type `TypeId` in a pattern, `TypeId` must be annotated with `#[derive(PartialEq, Eq)]`
\--\> C:\\Users\\ege.yetkin.cargo\\registry\\src\\index.crates.io-6f17d22bba15001f\\value-bag-1.0.0-alpha.9\\src\\internal\\cast\\primitive.rs:43:33
|
43 |   ...                           $const_ident =\> |v| Some(Internal::from(unsafe { &\*(\*v as \*const Se...
|                                 ^^^^^^^^^^^^
...
71 | / ...   to_internal!\[
72 | | ...       usize: (USIZE, OPTION_USIZE),
73 | | ...       u8: (U8, OPTION_U8),
74 | | ...       u16: (U16, OPTION_U16),
...  |
96 | | ...       String: (STRING, OPTION_STRING),
97 | | ...   \];
| |\______\_- in this macro invocation
|
= note: the traits must be derived, manual `impl`s are not sufficient
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
= note: this error originates in the macro `to_internal`
use crate::mqtt::{self, MqttMessage};
use serde::{Deserialize, Serialize};
use serde_json;
use sqlx::types::Json;
use sqlx::{Connection, Row};
use std::time::{SystemTime, UNIX_EPOCH};

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
struct payload {
    iv: i32,
    metrics: Vec<data_metrics>,
    ts: i32,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
struct data_metrics {
    name: String,
    timestamp: i64,
    value: f32,
    //Used concerete type instead of generic type for value, which makes the code more complicated.
    //In mqtt messages, consider using simple f32. Depending on the name of signal, we can seperate it
}

//Seperates mqqtt messages into topic and payload fields
pub fn db_control_flow(input: mqtt::MqttMessage) -> Result<(), Box<dyn Error>> {
    let payload_msg = input.payload;
    let topic_msg = input.topic;

    //Print the seperated fields of the mqtt message
    println!("\nDatabase module message payload :{:#?}\n", &payload_msg);
    println!("\nDatabase module message topic :{:#?}\n", &topic_msg);

    //parse the topic into fields
    //device_id is optional because topic might be for a NODE
    if let (message_type, mac_add) = extract_topic_parts(topic_msg) {
        println!("MAC Address = {}", mac_add); //a.k.a. NODE number
        println!("Message Type = {}", &message_type);

        //with match flow control the message type
        //depending on the type make proper function calls
        match message_type.as_str() {
            "NBIRTH" => println!("NBIRTH"),
            "NDEATH" => println!("NDEATH"),
            "DATA" => {
                let data = payload_parser(payload_msg);
                //DB_Values_Insert(data, client_no, Some(device_id)); //Buraya database'e göre değişiklik yapılacak
            }
            "NCMD" => println!("NCMD"),
            "DBIRTH" => println!("DBIRTH"),
            "DDEATH" => println!("DDEATH"),
            "DDATA" => println!("DDATA"),
            "DCMD" => println!("DCMD"),
            "STATE" => println!("STATE"),
            _ => println!("Unrecognized message type!"),
        };
    }
    Ok(())
}

//this function devides topic into fields

/*TAKES PAYLOAD AS JSON IN STRING TYPE, RETURNS PAYLOAD STRUCT */
//uses serde_json

//data base data insert function
//ADD ERROR HANDLING
pub fn DB_Values_Insert(data: payload, mac_no: String) -> Result<(), Box<dyn Error>> {
    let url = "postgresql://postgres:123456@localhost:5432/SunJrTestEge";
    let mut connection = sqlx::postgres::PgConnection::connect(url).await?;

    let vec_data_metrics: Vec<data_metrics> = data.metrics;

    /* let mut deviceID: String = client_no + "/" + device_id.unwrap_or_default().as_str(); */

    let deviceID: i32 = 1; //Default value untill devices table is active

    for metric in vec_data_metrics {
        let mut signal_id: i32 = 0;

        match metric.name.as_str() {
            "VBatt" => signal_id = 1,
            "TBatt" => signal_id = 2,
            "SOC" => signal_id = 3,
            "VOC" => signal_id = 4,
            "P" => signal_id = 5,
            _ => println!("Undefined signal id type!"),
        };

        let query =
            "INSERT INTO values_table (deviceid, signalid, value, timestamp) VALUES ($1, $2, $3, $4)";
        sqlx::query(query)
            .bind(&deviceID)
            .bind(&signal_id)
            .bind(&metric.value)
            .bind(&metric.timestamp)
            .await?;
    }
    Ok(())
}

fn extract_topic_parts(topic: String) -> (String, String) {
    let mut topic_parts = topic.split('/');
    let mac_add = topic_parts.next().unwrap_or_default().to_string();
    let message_type = topic_parts.next().unwrap_or_default().to_string();

    return (message_type, mac_add);
}
fn payload_parser(payload: String) -> payload {
    let data_forDB: payload = serde_json::from_str(payload.as_str()).expect("serde failed!");
    println!("{:#?}", data_forDB);
    return data_forDB;
}

So this is my database module. I suspect the problem lays here. Because rest of my program was working fine. I tried completely removing this database module and compile, still the same results.

Yuri Astrakhan
  • 8,808
  • 6
  • 63
  • 97
tonicChord
  • 11
  • 4
  • Could you show us a minimal version of the source code reproducing this problem? In general, both the source code and the full error messge are required to understand a problem. – Sven Marnach Jul 05 '23 at 14:23
  • Interesting. To be used in a `match`, a type has to derive `Eq` and `PartialEq` (so that “structural equality” works as expected). While `TypeId` derives `Eq`, it `#[derive_const(PartialEq)]`, which is some sort of compiler-internal derive mechanism. Not sure if this is a bug or a feature working correctly to prevent `TypeId` from being matched on. Certainly it seems like `TypeId` _should_ be matchable, as it's just a wrapper around `u64`. – BallpointBen Jul 05 '23 at 15:25
  • 1
    @BallpointBen It is not a bug; see my answer. – Chayim Friedman Jul 05 '23 at 15:40
  • I just added the new part of my program. I believe this part is causing some problems. Yet compiler does not show any specific location in the code that's why I am confused. – tonicChord Jul 06 '23 at 12:34

2 Answers2

0

Matching against TypeId used to work in the past, but it was changed in PR #103291 because TypeId is not a plain u64 and may, and is expected to, contain additional data in the future.

Since it seems that the stable version of value-bag does not do that, just downgrade the alpha version to the stable version in your Cargo.toml.

Alternatively, unset the environment variable VALUE_BAG_CAPTURE_CONST_TYPE_ID, it should also work.

Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77
0

It seems there was a compiler bug. I updated cargo then the problem just disappeared.

tonicChord
  • 11
  • 4
  • How did you update Cargo? Because if by rustup, and you had old toolchain, this error should have not appeared. – Chayim Friedman Jul 06 '23 at 14:24
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 12 '23 at 16:33
  • I was using an older version of nightly. I am guessing that caused some problems. And yes I just used rustup command. – tonicChord Jul 18 '23 at 07:29
  • Also here are my active toolchains if it gives any idea installed toolchains -------------------- stable-x86_64-pc-windows-gnu stable-x86_64-pc-windows-msvc nightly-x86_64-pc-windows-msvc (default) active toolchain ---------------- nightly-x86_64-pc-windows-msvc (default) rustc 1.72.0-nightly (df77afbca 2023-06-12) – tonicChord Jul 18 '23 at 07:30