299 lines
9.1 KiB
Rust
299 lines
9.1 KiB
Rust
use crate::{
|
|
state_variables::StateVariable,
|
|
variable_types::{StateValue, UpnpVarType},
|
|
};
|
|
|
|
/// Trait pour accéder aux propriétés et contraintes d'une variable UPnP.
|
|
///
|
|
/// Ce trait fournit une interface uniforme pour interroger les métadonnées,
|
|
/// contraintes et comportements d'une variable UPnP, qu'il s'agisse d'une
|
|
/// définition ([`StateVariable`]) ou d'une instance ([`StateVarInstance`]).
|
|
///
|
|
/// # Architecture
|
|
///
|
|
/// Le trait utilise le pattern "trait avec implémentation par défaut" :
|
|
/// - Une seule méthode requise : [`get_definition`](Self::get_definition)
|
|
/// - Toutes les autres méthodes sont implémentées par défaut en déléguant à la définition
|
|
///
|
|
/// Cela permet une interface cohérente entre modèles et instances sans duplication de code.
|
|
///
|
|
/// # Hiérarchie
|
|
///
|
|
/// ```text
|
|
/// UpnpVariable
|
|
/// ├─> StateVariable (get_definition() retourne self)
|
|
/// └─> StateVarInstance (get_definition() retourne self.definition)
|
|
/// ```
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// fn display_variable_info<V: UpnpVariable>(var: &V) {
|
|
/// println!("Variable: {}", var.get_definition().get_name());
|
|
///
|
|
/// if var.has_default() {
|
|
/// println!("Default: {:?}", var.get_default());
|
|
/// }
|
|
///
|
|
/// if var.has_range() {
|
|
/// println!("Has range constraints");
|
|
/// }
|
|
///
|
|
/// if var.has_allowed_values() {
|
|
/// println!("Has allowed values list");
|
|
/// }
|
|
/// }
|
|
/// ```
|
|
pub trait UpnpVariable {
|
|
/// Retourne une référence vers la définition de la variable.
|
|
///
|
|
/// Cette méthode est la base de toutes les autres méthodes du trait.
|
|
///
|
|
/// # Implementation
|
|
///
|
|
/// - Pour [`StateVariable`] : retourne `self`
|
|
/// - Pour [`StateVarInstance`] : retourne `self.definition`
|
|
fn get_definition(&self) -> &StateVariable;
|
|
|
|
/// Indique si la variable a un pas (step) défini.
|
|
///
|
|
/// Le pas définit l'incrément minimal entre deux valeurs valides pour
|
|
/// les types numériques.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// `true` si un pas est défini, `false` sinon.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// if var.has_step() {
|
|
/// println!("Step: {:?}", var.get_step());
|
|
/// }
|
|
/// ```
|
|
fn has_step(&self) -> bool {
|
|
self.get_definition().step.is_some()
|
|
}
|
|
|
|
/// Retourne le pas (step) de la variable s'il est défini.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// - `Some(StateValue)` si un pas est défini
|
|
/// - `None` sinon
|
|
///
|
|
/// # See also
|
|
///
|
|
/// - [`has_step`](Self::has_step) pour tester l'existence
|
|
fn get_step(&self) -> Option<StateValue> {
|
|
self.get_definition().step.clone()
|
|
}
|
|
|
|
/// Indique si la variable a une plage de valeurs (range) définie.
|
|
///
|
|
/// La plage définit les valeurs minimale et maximale acceptables.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// `true` si une plage est définie, `false` sinon.
|
|
fn has_range(&self) -> bool {
|
|
self.get_definition().value_range.is_some()
|
|
}
|
|
|
|
/// Indique si la variable est modifiable.
|
|
///
|
|
/// Une variable non modifiable est en lecture seule.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// `true` si la variable peut être modifiée, `false` sinon.
|
|
fn is_modifiable(&self) -> bool {
|
|
self.get_definition().modifiable
|
|
}
|
|
|
|
/// Indique si la variable a des conditions d'événement définies.
|
|
///
|
|
/// Les conditions d'événement déterminent quand des notifications
|
|
/// doivent être envoyées lors de changements de valeur.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// `true` si au moins une condition d'événement existe, `false` sinon.
|
|
///
|
|
/// # Note
|
|
///
|
|
/// Retourne `false` si le lock est empoisonné (poisoned).
|
|
fn has_event_conditions(&self) -> bool {
|
|
let guard = self.get_definition().event_conditions.read().unwrap();
|
|
!guard.is_empty()
|
|
}
|
|
|
|
/// Vérifie si une condition d'événement spécifique existe.
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `name` - Le nom de la condition à rechercher
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// `true` si la condition existe, `false` sinon.
|
|
///
|
|
/// # Note
|
|
///
|
|
/// Retourne `false` si le lock est empoisonné (poisoned).
|
|
fn has_event_condition(&self, name: &String) -> bool {
|
|
let guard = self.get_definition().event_conditions.read().unwrap();
|
|
guard.contains_key(name)
|
|
}
|
|
|
|
/// Indique si la variable a une description non vide.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// `true` si une description existe et n'est pas vide, `false` sinon.
|
|
fn has_description(&self) -> bool {
|
|
!self.get_definition().description.is_empty()
|
|
}
|
|
|
|
/// Retourne la description de la variable.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// La description sous forme de `String`. Peut être vide.
|
|
///
|
|
/// # See also
|
|
///
|
|
/// - [`has_description`](Self::has_description) pour tester si non vide
|
|
fn get_description(&self) -> String {
|
|
self.get_definition().description.clone()
|
|
}
|
|
|
|
/// Indique si la variable a une valeur par défaut définie explicitement.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// `true` si une valeur par défaut est explicitement définie, `false` sinon.
|
|
///
|
|
/// # Note
|
|
///
|
|
/// Même si cette méthode retourne `false`, [`get_default`](Self::get_default)
|
|
/// retournera toujours une valeur (la valeur par défaut du type).
|
|
fn has_default(&self) -> bool {
|
|
self.get_definition().default_value.is_some()
|
|
}
|
|
|
|
/// Retourne la valeur par défaut de la variable.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// La valeur par défaut. Si aucune valeur par défaut n'est explicitement
|
|
/// définie, retourne la valeur par défaut du type de la variable
|
|
/// (ex: 0 pour les entiers, chaîne vide pour String, etc.).
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// let default = var.get_default();
|
|
/// println!("Default value: {:?}", default);
|
|
/// ```
|
|
fn get_default(&self) -> StateValue {
|
|
self.get_definition()
|
|
.default_value
|
|
.clone()
|
|
.unwrap_or_else(|| self.get_definition().as_state_var_type().default_value())
|
|
}
|
|
|
|
/// Indique si la variable a une liste de valeurs autorisées.
|
|
///
|
|
/// Lorsqu'une liste de valeurs autorisées est définie, seules ces valeurs
|
|
/// sont acceptables pour la variable.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// `true` si une liste non vide de valeurs autorisées existe, `false` sinon.
|
|
///
|
|
/// # Note
|
|
///
|
|
/// Retourne `false` si le lock est empoisonné (poisoned).
|
|
fn has_allowed_values(&self) -> bool {
|
|
let guard = self.get_definition().allowed_values.read().unwrap();
|
|
|
|
!guard.is_empty()
|
|
}
|
|
|
|
/// Vérifie si une valeur fait partie des valeurs autorisées.
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `value` - La valeur à vérifier
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// `true` si la valeur est dans la liste des valeurs autorisées, `false` sinon.
|
|
/// Retourne également `false` si aucune liste de valeurs autorisées n'est définie
|
|
/// ou si le lock est empoisonné.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// let value = StateValue::String("ON".to_string());
|
|
/// if var.is_an_allowed_value(&value) {
|
|
/// println!("Value is allowed");
|
|
/// }
|
|
/// ```
|
|
///
|
|
/// # Note
|
|
///
|
|
/// Si aucune liste de valeurs autorisées n'est définie, cette méthode
|
|
/// retourne `false`. Utilisez [`has_allowed_values`](Self::has_allowed_values)
|
|
/// pour distinguer "pas de liste" de "valeur non autorisée".
|
|
fn is_an_allowed_value(&self, value: &StateValue) -> bool {
|
|
let guard = self.get_definition().allowed_values.read().unwrap();
|
|
|
|
guard.contains(value)
|
|
}
|
|
|
|
/// Indique si la variable envoie des notifications d'événement.
|
|
///
|
|
/// Les notifications d'événement sont envoyées aux abonnés lorsque
|
|
/// la valeur de la variable change.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// `true` si les notifications sont activées, `false` sinon.
|
|
///
|
|
/// # See also
|
|
///
|
|
/// - [`has_event_conditions`](Self::has_event_conditions) pour vérifier
|
|
/// les conditions d'envoi d'événements
|
|
fn is_sending_notification(&self) -> bool {
|
|
self.get_definition().send_events
|
|
}
|
|
|
|
/// Indique si la variable a un parser de valeur personnalisé.
|
|
///
|
|
/// Un parser personnalisé est utilisé pour convertir des chaînes de
|
|
/// caractères en valeurs typées. Disponible uniquement pour les variables
|
|
/// de type String.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// `true` si un parser est défini, `false` sinon.
|
|
fn has_value_parser(&self) -> bool {
|
|
self.get_definition().parse.is_some()
|
|
}
|
|
|
|
/// Indique si la variable a un marshaler de valeur personnalisé.
|
|
///
|
|
/// Un marshaler personnalisé est utilisé pour sérialiser des valeurs
|
|
/// en chaînes de caractères. Disponible uniquement pour les variables
|
|
/// de type String.
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// `true` si un marshaler est défini, `false` sinon.
|
|
fn has_value_marshaler(&self) -> bool {
|
|
self.get_definition().marshal.is_some()
|
|
}
|
|
}
|