robot_description_builder/material/
data.rs1use std::sync::Arc;
7
8use crate::utils::{ArcLock, ArcRW, ErroredRead};
9
10#[cfg(feature = "urdf")]
11use crate::to_rdf::to_urdf::ToURDF;
12#[cfg(feature = "xml")]
13use quick_xml::{events::attributes::Attribute, name::QName};
14
15#[derive(Debug, PartialEq, Clone)]
17pub enum MaterialData {
18 Color(f32, f32, f32, f32),
22 Texture(String),
24}
25
26#[cfg(feature = "urdf")]
27impl ToURDF for MaterialData {
28 fn to_urdf(
29 &self,
30 writer: &mut quick_xml::Writer<std::io::Cursor<Vec<u8>>>,
31 _urdf_config: &crate::to_rdf::to_urdf::URDFConfig,
32 ) -> Result<(), quick_xml::Error> {
33 match self {
34 MaterialData::Color(red, green, blue, alpha) => {
35 writer
36 .create_element("color")
37 .with_attribute(Attribute {
38 key: QName(b"rgba"),
39 value: format!("{} {} {} {}", red, green, blue, alpha)
40 .as_bytes()
41 .into(),
42 })
43 .write_empty()?;
44 Ok(())
45 }
46 MaterialData::Texture(texture_path) => {
47 writer
48 .create_element("texture")
49 .with_attribute(Attribute {
50 key: QName(b"filename"),
51 value: texture_path.clone().as_bytes().into(),
52 })
53 .write_empty()?;
54 Ok(())
55 }
56 }
57 }
58}
59
60#[derive(Debug)]
64pub enum MaterialDataReference<'a> {
65 Direct(&'a MaterialData),
67 Global(ArcLock<MaterialData>),
69}
70
71impl<'a> MaterialDataReference<'a> {
72 pub fn same_material_data(&self, other: &MaterialDataReference) -> bool {
77 #[allow(unreachable_code)] match (self, other) {
79 (MaterialDataReference::Direct(left), MaterialDataReference::Direct(right)) => {
80 left == right
81 }
82 (MaterialDataReference::Direct(left), MaterialDataReference::Global(right)) => {
83 match !right.is_poisoned() {
84 true => (*left).clone() == right.read().unwrap().clone(), false => {
86 *right.write().map_err(|err| err.into_inner()).unwrap() = (*left).clone();
88 todo!("Unpoisoning is still a nightly-only experimental feature. (mutex_unpoison #96469)");
89 true
90 }
91 }
92 }
93 (MaterialDataReference::Global(left), MaterialDataReference::Direct(right)) => {
94 match !left.is_poisoned() {
95 true => (*right).clone() == left.read().unwrap().clone(), false => {
97 *left.write().map_err(|err| err.into_inner()).unwrap() = (*right).clone();
99 todo!("Unpoisoning is still a nightly-only experimental feature. (mutex_unpoison #96469)");
100 true
101 }
102 }
103 }
104 (MaterialDataReference::Global(left), MaterialDataReference::Global(right)) => {
105 Arc::ptr_eq(left, right)
106 || left.read().unwrap().clone() == right.read().unwrap().clone() }
108 }
109 }
110}
111
112impl<'a> PartialEq for MaterialDataReference<'a> {
113 fn eq(&self, other: &Self) -> bool {
114 match (self, other) {
115 (Self::Direct(l0), Self::Direct(r0)) => l0 == r0,
116 (Self::Global(l0), Self::Global(r0)) => Arc::ptr_eq(l0, r0),
117 _ => false,
118 }
119 }
120}
121
122impl<'a> From<&'a MaterialData> for MaterialDataReference<'a> {
123 fn from(value: &'a MaterialData) -> Self {
124 Self::Direct(value)
125 }
126}
127
128impl<'a> From<ArcLock<MaterialData>> for MaterialDataReference<'a> {
129 fn from(value: ArcLock<MaterialData>) -> Self {
130 MaterialDataReference::Global(value)
131 }
132}
133
134impl<'a> TryFrom<MaterialDataReference<'a>> for MaterialData {
135 type Error = std::sync::PoisonError<ErroredRead<ArcLock<MaterialData>>>;
136
137 fn try_from(value: MaterialDataReference) -> Result<Self, Self::Error> {
138 match value {
139 MaterialDataReference::Direct(data) => Ok(data.clone()),
140 MaterialDataReference::Global(arc_data) => {
141 let data_ref = arc_data.mread().map(|data| data.clone());
142 data_ref
143 }
144 }
145 }
146}