iot-core 0.0.1

Core types for the iot-protocols SDK: Thing model, IotClient trait, errors, paths, protocol bindings.
Documentation
//! Protocol-agnostic property addressing.
//!
//! A [`PropertyPath`] points at exactly one property of one feature of one
//! Thing. The actual physical location (Modbus register, MQTT topic, CoAP
//! URI, OPC UA NodeId) is held by a [`crate::binding::ProtocolBinding`]
//! looked up via [`crate::binding::ThingMapping`].

use core::fmt;

use crate::thing::{FeatureId, PropertyId, ThingId};

/// Identifies one property in a Thing — protocol-agnostic.
///
/// `Ord` is implemented so paths can key a `BTreeMap` (the default Thing
/// mapping container in `no_std + alloc`).
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct PropertyPath {
    /// Owning Thing.
    #[cfg_attr(feature = "serde", serde(rename = "thingId"))]
    pub thing: ThingId,
    /// Feature inside the Thing.
    #[cfg_attr(feature = "serde", serde(rename = "featureId"))]
    pub feature: FeatureId,
    /// Property inside the feature.
    #[cfg_attr(feature = "serde", serde(rename = "propertyId"))]
    pub property: PropertyId,
}

impl PropertyPath {
    /// Construct from already-validated identifiers.
    pub fn new(thing: ThingId, feature: FeatureId, property: PropertyId) -> Self {
        Self {
            thing,
            feature,
            property,
        }
    }
}

impl fmt::Display for PropertyPath {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // Canonical text form: `thingId/feature/property`. Used by the
        // gateway crate for log lines and as the default MQTT topic suffix.
        write!(
            f,
            "{}/{}/{}",
            self.thing.as_str(),
            self.feature.as_str(),
            self.property.as_str()
        )
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn display_canonical() {
        let p = PropertyPath::new(
            ThingId::new("acme:pump-7"),
            FeatureId::new("temperature"),
            PropertyId::new("value"),
        );
        assert_eq!(p.to_string(), "acme:pump-7/temperature/value");
    }
}