432 lines
13 KiB
Rust
432 lines
13 KiB
Rust
use std::{
|
|
collections::HashMap,
|
|
fmt,
|
|
sync::Arc,
|
|
};
|
|
|
|
use std::sync::RwLock;
|
|
use xmltree::{Element, XMLNode};
|
|
|
|
use crate::{
|
|
UpnpObjectType, UpnpTyped,
|
|
object_trait::{UpnpModel, UpnpObject},
|
|
state_variables::{
|
|
StateConditionFunc, StateVarInstance, StateVariable, StringValueParser, ValueSerializer,
|
|
variable_trait::UpnpVariable,
|
|
},
|
|
value_ranges::ValueRange,
|
|
variable_types::{StateValue, StateValueError, StateVarType, UpnpVarType},
|
|
};
|
|
|
|
impl UpnpTyped for StateVariable {
|
|
fn as_upnp_object_type(&self) -> &UpnpObjectType {
|
|
&self.object
|
|
}
|
|
}
|
|
|
|
impl UpnpVarType for StateVariable {
|
|
fn as_state_var_type(&self) -> StateVarType {
|
|
self.value_type.as_state_var_type() // utilise ton From<&StateValue> existant
|
|
}
|
|
}
|
|
|
|
impl UpnpObject for StateVariable {
|
|
fn to_xml_element(&self) -> Element {
|
|
// Création de l'élément racine <stateVariable>
|
|
let mut root = Element::new("stateVariable");
|
|
root.attributes.insert(
|
|
"sendEvents".to_string(),
|
|
if self.send_events { "yes" } else { "no" }.to_string(),
|
|
);
|
|
|
|
// <name>
|
|
let mut name_elem = Element::new("name");
|
|
name_elem
|
|
.children
|
|
.push(XMLNode::Text(self.get_name().clone()));
|
|
|
|
// <dataType>
|
|
let mut datatype_elem = Element::new("dataType");
|
|
datatype_elem
|
|
.children
|
|
.push(XMLNode::Text(self.value_type.to_string())); // StateVarType doit impl Display
|
|
|
|
// <defaultValue> si défini
|
|
if let Some(default) = &self.default_value {
|
|
let mut def_elem = Element::new("defaultValue");
|
|
def_elem.children.push(XMLNode::Text(default.to_string()));
|
|
root.children.push(XMLNode::Element(def_elem));
|
|
}
|
|
|
|
// <allowedValueList> si défini
|
|
let av = self.allowed_values.read().unwrap();
|
|
if !av.is_empty() {
|
|
let mut list_elem = Element::new("allowedValueList");
|
|
for val in av.iter() {
|
|
let mut val_elem = Element::new("allowedValue");
|
|
val_elem.children.push(XMLNode::Text(val.to_string()));
|
|
list_elem.children.push(XMLNode::Element(val_elem));
|
|
}
|
|
root.children.push(XMLNode::Element(list_elem));
|
|
}
|
|
|
|
// <allowedValueRange> si défini
|
|
if let Some(range) = &self.value_range {
|
|
let mut range_elem = Element::new("allowedValueRange");
|
|
|
|
let mut min_elem = Element::new("minimum");
|
|
min_elem
|
|
.children
|
|
.push(XMLNode::Text(range.get_minimum().to_string()));
|
|
range_elem.children.push(XMLNode::Element(min_elem));
|
|
|
|
let mut max_elem = Element::new("maximum");
|
|
max_elem
|
|
.children
|
|
.push(XMLNode::Text(range.get_maximum().to_string()));
|
|
range_elem.children.push(XMLNode::Element(max_elem));
|
|
|
|
if let Some(step) = &self.step {
|
|
let mut step_elem = Element::new("step");
|
|
step_elem.children.push(XMLNode::Text(step.to_string()));
|
|
range_elem.children.push(XMLNode::Element(step_elem));
|
|
}
|
|
|
|
root.children.push(XMLNode::Element(range_elem));
|
|
}
|
|
|
|
// Ajouter les enfants communs
|
|
root.children.push(XMLNode::Element(name_elem));
|
|
root.children.push(XMLNode::Element(datatype_elem));
|
|
|
|
root
|
|
}
|
|
}
|
|
|
|
impl UpnpModel for StateVariable {
|
|
type Instance = StateVarInstance;
|
|
}
|
|
|
|
impl Clone for StateVariable {
|
|
fn clone(&self) -> Self {
|
|
// clone safe des structures protégées par RwLock en prenant un read lock
|
|
let event_conditions_clone = {
|
|
// si le lock est "poisoned" on panic - tu peux adapter la gestion si tu veux
|
|
let guard = self
|
|
.event_conditions
|
|
.read().unwrap();
|
|
// nécessite que Key: Clone, Value: Clone
|
|
Arc::new(RwLock::new(guard.clone()))
|
|
};
|
|
|
|
let allowed_values_clone = {
|
|
let guard = self
|
|
.allowed_values
|
|
.read().unwrap();
|
|
Arc::new(RwLock::new(guard.clone()))
|
|
};
|
|
|
|
Self {
|
|
object: self.object.clone(),
|
|
value_type: self.value_type.clone(),
|
|
step: self.step.clone(),
|
|
modifiable: self.modifiable,
|
|
event_conditions: event_conditions_clone,
|
|
description: self.description.clone(),
|
|
default_value: self.default_value.clone(),
|
|
value_range: self.value_range.clone(),
|
|
allowed_values: allowed_values_clone,
|
|
send_events: self.send_events,
|
|
// parse et marshal sont typiquement des Arc<dyn ...> — on clone l'Arc (shallow).
|
|
// Deep-cloner une closure ou un trait-objet n'est pas possible en général.
|
|
parse: self.parse.clone(),
|
|
marshal: self.marshal.clone(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl fmt::Debug for StateVariable {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
f.debug_struct("StateVariable")
|
|
.field("object", &self.object)
|
|
.field("value_type", &self.value_type)
|
|
.field("step", &self.step)
|
|
.field("modifiable", &self.modifiable)
|
|
.field(
|
|
"event_conditions",
|
|
&format_args!(
|
|
"len={}",
|
|
self.event_conditions.read().unwrap().len()
|
|
),
|
|
)
|
|
.field("description", &self.description)
|
|
.field("default_value", &self.default_value)
|
|
.field("value_range", &self.value_range)
|
|
.field(
|
|
"allowed_values",
|
|
&format_args!(
|
|
"len={}",
|
|
self.allowed_values.read().unwrap().len()
|
|
),
|
|
)
|
|
.field("send_events", &self.send_events)
|
|
.field(
|
|
"parse",
|
|
&self
|
|
.parse
|
|
.as_ref()
|
|
.map(|_| "Some(StringValueParser)")
|
|
.unwrap_or("None"),
|
|
)
|
|
.field(
|
|
"marshal",
|
|
&self
|
|
.marshal
|
|
.as_ref()
|
|
.map(|_| "Some(ValueSerializer)")
|
|
.unwrap_or("None"),
|
|
)
|
|
.finish()
|
|
}
|
|
}
|
|
|
|
impl UpnpVariable for StateVariable {
|
|
fn get_definition(&self) -> &StateVariable {
|
|
return self;
|
|
}
|
|
}
|
|
|
|
impl StateVariable {
|
|
pub fn new(vartype: StateVarType, name: String) -> StateVariable {
|
|
Self {
|
|
object: UpnpObjectType {
|
|
name,
|
|
object_type: "StateVariable".to_string(),
|
|
},
|
|
value_type: vartype.clone(),
|
|
step: None,
|
|
modifiable: true,
|
|
event_conditions: Arc::new(RwLock::new(HashMap::new())),
|
|
description: "".to_string(),
|
|
default_value: None,
|
|
value_range: None,
|
|
allowed_values: Arc::new(RwLock::new(Vec::new())),
|
|
send_events: false,
|
|
parse: None,
|
|
marshal: None,
|
|
}
|
|
}
|
|
|
|
pub fn set_step(&mut self, step: StateValue) -> Result<(), StateValueError> {
|
|
if self.as_state_var_type() != step.as_state_var_type() {
|
|
return Err(StateValueError::TypeError("Bad step type".to_string()));
|
|
}
|
|
|
|
self.step = Some(step);
|
|
Ok(())
|
|
}
|
|
|
|
pub fn set_range(&mut self, min: &StateValue, max: &StateValue) -> Result<(), StateValueError> {
|
|
if self.as_state_var_type() != min.as_state_var_type() {
|
|
return Err(StateValueError::TypeError("Bad range type".to_string()));
|
|
}
|
|
|
|
let range = ValueRange::new(min, max)?; // ? propage l'erreur si elle existe
|
|
self.value_range = Some(range);
|
|
Ok(())
|
|
}
|
|
|
|
pub fn update_minimum(&mut self, min: &StateValue) -> Result<(), StateValueError> {
|
|
if !self.has_range() {
|
|
return Err(StateValueError::RangeError(
|
|
"No range specified for this variable".to_string(),
|
|
));
|
|
}
|
|
if self
|
|
.value_range
|
|
.as_ref()
|
|
.expect("Range is not defined")
|
|
.as_state_var_type()
|
|
!= min.as_state_var_type()
|
|
{
|
|
return Err(StateValueError::TypeError(
|
|
"new minimum is not the same than state variable".to_string(),
|
|
));
|
|
}
|
|
self.value_range
|
|
.as_mut()
|
|
.expect("Range is not defined")
|
|
.set_minimum(min);
|
|
return Ok(());
|
|
}
|
|
|
|
pub fn update_maximum(&mut self, min: &StateValue) -> Result<(), StateValueError> {
|
|
if !self.has_range() {
|
|
return Err(StateValueError::RangeError(
|
|
"No range specified for this variable".to_string(),
|
|
));
|
|
}
|
|
if self
|
|
.value_range
|
|
.as_ref()
|
|
.expect("Range is not defined")
|
|
.as_state_var_type()
|
|
!= min.as_state_var_type()
|
|
{
|
|
return Err(StateValueError::TypeError(
|
|
"new minimum is not the same than state variable".to_string(),
|
|
));
|
|
}
|
|
self.value_range
|
|
.as_mut()
|
|
.expect("Range is not defined")
|
|
.set_maximum(min);
|
|
return Ok(());
|
|
}
|
|
|
|
pub fn get_range(&self) -> Option<&ValueRange> {
|
|
return self.value_range.as_ref();
|
|
}
|
|
|
|
pub fn set_modifiable(&mut self) {
|
|
self.modifiable = true;
|
|
}
|
|
|
|
pub fn set_not_modifiable(&mut self) {
|
|
self.modifiable = false;
|
|
}
|
|
|
|
pub fn add_event_condition(&self, name: String, func: StateConditionFunc) {
|
|
// on lock en écriture
|
|
let mut guard = self.event_conditions.write().unwrap();
|
|
guard.insert(name, func);
|
|
// le lock est automatiquement relâché ici (RAII)
|
|
}
|
|
|
|
pub fn remove_event_condition(&self, name: &str) {
|
|
let mut guard = self.event_conditions.write().unwrap();
|
|
guard.remove(name);
|
|
}
|
|
|
|
pub fn clear_event_conditions(&mut self) {
|
|
let mut guard = self.event_conditions.write().unwrap();
|
|
guard.clear()
|
|
}
|
|
|
|
pub fn set_description(&mut self, description: String) {
|
|
self.description = description;
|
|
}
|
|
|
|
pub fn set_default(&mut self, value: &StateValue) -> Result<(), StateValueError> {
|
|
if self.as_state_var_type() != value.as_state_var_type() {
|
|
return Err(StateValueError::TypeError(
|
|
"value does not have the right type".to_string(),
|
|
));
|
|
}
|
|
self.default_value = Some(value.clone());
|
|
return Ok(());
|
|
}
|
|
|
|
pub fn unset_default(&mut self) {
|
|
self.default_value = None;
|
|
}
|
|
|
|
pub fn extend_allowed_values(&mut self, values: &[StateValue]) -> Result<(), StateValueError> {
|
|
let mut av = self
|
|
.allowed_values
|
|
.write().unwrap();
|
|
|
|
for v in values {
|
|
if self.as_state_var_type() == v.as_state_var_type() {
|
|
av.push(v.clone());
|
|
} else {
|
|
return Err(StateValueError::TypeError(
|
|
"new allowed value does not have the right type".to_string(),
|
|
));
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn push_allowed_value(&mut self, value: &StateValue) -> Result<(), StateValueError> {
|
|
let mut av = self
|
|
.allowed_values
|
|
.write().unwrap();
|
|
|
|
if self.as_state_var_type() == value.as_state_var_type() {
|
|
av.push(value.clone());
|
|
} else {
|
|
return Err(StateValueError::TypeError(
|
|
"new allowed value does not have the right type".to_string(),
|
|
));
|
|
}
|
|
|
|
return Ok(());
|
|
}
|
|
|
|
pub fn set_send_notification(&mut self) {
|
|
self.send_events = true;
|
|
}
|
|
|
|
pub fn unset_send_notification(&mut self) {
|
|
self.send_events = false;
|
|
}
|
|
|
|
pub fn set_value_parser(&mut self, parser: StringValueParser) -> Result<(), StateValueError> {
|
|
if self.as_state_var_type() == StateVarType::String {
|
|
self.parse = Some(parser);
|
|
return Ok(());
|
|
}
|
|
return Err(StateValueError::TypeError(
|
|
"Only String variables can have a parser".to_string(),
|
|
));
|
|
}
|
|
|
|
pub fn unset_value_parser(&mut self) {
|
|
self.parse = None;
|
|
}
|
|
|
|
pub fn set_value_marshaler(
|
|
&mut self,
|
|
marshaler: ValueSerializer,
|
|
) -> Result<(), StateValueError> {
|
|
if self.as_state_var_type() == StateVarType::String {
|
|
self.marshal = Some(marshaler);
|
|
return Ok(());
|
|
}
|
|
return Err(StateValueError::TypeError(
|
|
"Only String variables can have a marshaler".to_string(),
|
|
));
|
|
}
|
|
|
|
pub fn unset_value_marshaler(&mut self) {
|
|
self.marshal = None;
|
|
}
|
|
|
|
/// Retourne le type de données de cette variable.
|
|
pub fn get_data_type(&self) -> &StateVarType {
|
|
&self.value_type
|
|
}
|
|
|
|
/// Retourne la valeur par défaut si définie.
|
|
pub fn get_default_value(&self) -> Option<&StateValue> {
|
|
self.default_value.as_ref()
|
|
}
|
|
|
|
/// Retourne le step si défini.
|
|
pub fn get_step(&self) -> Option<&StateValue> {
|
|
self.step.as_ref()
|
|
}
|
|
|
|
/// Retourne les valeurs autorisées.
|
|
pub fn get_allowed_values(&self) -> Vec<StateValue> {
|
|
self.allowed_values.read().unwrap().clone()
|
|
}
|
|
|
|
/// Indique si cette variable envoie des notifications d'événements.
|
|
pub fn sends_events(&self) -> bool {
|
|
self.send_events
|
|
}
|
|
}
|