1use std::sync::{Arc, Mutex, Weak};
4use std::collections::HashMap;
5use std::fmt::{self, Debug};
6use std::future::Future;
7use std::any::Any;
8
9use crate::dev::{All, Named, ToNames, ToNamesNotAll};
10use crate::database::{GetPropSpec, SetPropSpec};
11use crate::error::{Error, ErrorKind, Result};
12use crate::name::{self, ArcName, Name};
13use crate::value::Spectrum;
14
15use super::{reserved_name, Model, RESERVED_ATTRS};
16use super::dev::{AnyDev, Dev};
17use super::server::Server;
18use super::def::ClassDef;
19
20
21pub(super) trait AnyClass: Debug + Send + Sync {
23
24 fn name(&self) -> &Arc<str>;
26
27 fn index(&self) -> usize;
30
31 fn add_dev(&self, name: &str) -> Result<Arc<dyn AnyDev>>;
33
34 fn into_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync>;
36
37}
38
39pub struct Class<M: Model> {
42 name: Arc<str>,
45 index: usize,
47 this: Weak<Self>,
49 server: Arc<Server>,
50 def: Arc<ClassDef<M>>,
51 attr_props: Mutex<HashMap<ArcName, Arc<[Named<Spectrum<str>>]>>>,
54}
55
56impl<M: Model> Class<M> {
57
58 pub(super) fn new(server: Arc<Server>, def: Arc<ClassDef<M>>, index: usize) -> Arc<Self> {
61 Arc::new_cyclic(|this| Self {
62 name: Arc::from(&*def.name),
63 index,
64 this: this.clone(),
65 server,
66 def,
67 attr_props: Mutex::new(HashMap::new()),
68 })
69 }
70
71 #[inline]
73 pub fn name(&self) -> &str {
74 &self.name
75 }
76
77 #[inline]
79 pub fn server(&self) -> &Server {
80 &self.server
81 }
82
83 pub async fn list_prop_async(&self, filter: &str) -> Result<Spectrum<str>> {
90 self.server().database().list_class_prop_async(&self.name, filter).await
91 }
92
93 pub fn list_prop(&self, filter: &str) -> Result<Spectrum<str>> {
95 self.server().database().list_class_prop(&self.name, filter)
96 }
97
98 pub fn get_prop_async<Spec, Names: ToNames>(&self, names: Names) -> impl Future<Output = Result<Spec::Output>> + Send
101 where
102 Spec: GetPropSpec<Names>,
103 {
104 self.server().database().get_class_prop_async::<Spec, Names>(&self.name, names)
105 }
106
107 pub fn get_prop<Spec, Names: ToNames>(&self, names: Names) -> Result<Spec::Output>
109 where
110 Spec: GetPropSpec<Names>,
111 {
112 self.server().database().get_class_prop::<Spec, Names>(&self.name, names)
113 }
114
115 pub fn set_prop_async<'a, Spec>(&'a self, spec: Spec) -> impl Future<Output = Result<()>> + Send
117 where
118 Spec: SetPropSpec<'a>,
119 {
120 self.server().database().set_class_prop_async(&self.name, spec)
121 }
122
123 pub fn set_prop<'a, Spec>(&'a self, spec: Spec) -> Result<()>
125 where
126 Spec: SetPropSpec<'a>,
127 {
128 self.server().database().set_class_prop(&self.name, spec)
129 }
130
131 pub fn delete_prop_async<Names: ToNamesNotAll>(&self, names: Names) -> impl Future<Output = Result<()>> + Send {
133 self.server().database().delete_class_prop_async(&self.name, names)
134 }
135
136 pub fn delete_prop<Names: ToNamesNotAll>(&self, names: Names) -> Result<()> {
138 self.server().database().delete_class_prop(&self.name, names)
139 }
140
141 pub(super) async fn attr_props(&self, names: &[&str]) -> Result<Vec<Arc<[Named<Spectrum<str>>]>>> {
152
153 let missing = {
155 let attr_props = self.attr_props.lock().unwrap();
156 names.iter()
157 .copied()
158 .filter(|name| !attr_props.contains_key(Name::new(name)))
159 .filter(|name| reserved_name(name, RESERVED_ATTRS).is_none())
160 .collect::<Vec<_>>()
161 };
162
163 if !missing.is_empty() {
164
165 let fetched = self.server()
166 .database()
167 .get_class_attr_prop_async::<Spectrum<str>, _, _>(&self.name, missing.as_slice(), All).await?;
168
169 let mut attr_props = self.attr_props.lock().unwrap();
170 for (name, props) in missing.into_iter().zip(fetched) {
171 attr_props.insert(ArcName::from(name), Arc::from(props?));
172 }
173
174 }
175
176 let attr_props = self.attr_props.lock().unwrap();
177 Ok(names
178 .iter()
179 .map(|name| attr_props.get(Name::new(name))
180 .map_or_else(|| Arc::from([]), Arc::clone))
181 .collect())
182
183 }
184
185 #[inline]
187 pub fn def(&self) -> &ClassDef<M> {
188 &self.def
189 }
190
191 pub fn add_dev(&self, name: &str) -> Result<Arc<Dev<M>>> {
198
199 if !name::check_tango_dev_name(name) {
200 return Err(Error::new(ErrorKind::DevNameInvalid)
201 .with_description(format!("Device {name:?} has an invalid name, it should be \
202 domain/family/member, each part made of letters, digits, '_' and '-', at most 85 long")));
203 }
204
205 let core = self.server.core_checked()?;
206 let mut server_devs = core.devs.lock().unwrap();
207 if server_devs.contains_key(Name::new(name)) {
208 return Err(Error::new(ErrorKind::DevAlreadyDefined)
209 .with_description(format!("Device {name:?} is already defined on the server")));
210 }
211
212 let name = Arc::<str>::from(name);
213 let dev = Dev::new(self.this.upgrade().unwrap(), Arc::clone(&name));
215 server_devs.insert(ArcName::from(name), Arc::clone(&dev) as Arc<dyn AnyDev>);
216 drop(server_devs);
217
218 core.pending.lock().unwrap().added.push(Arc::clone(&dev) as Arc<dyn AnyDev>);
219 Ok(dev)
220
221 }
222
223}
224
225impl<M: Model> AnyClass for Class<M> {
226
227 #[inline]
228 fn name(&self) -> &Arc<str> {
229 &self.name
230 }
231
232 #[inline]
233 fn index(&self) -> usize {
234 self.index
235 }
236
237 fn add_dev(&self, name: &str) -> Result<Arc<dyn AnyDev>> {
238 Class::add_dev(self, name).map(|dev| dev as Arc<dyn AnyDev>)
239 }
240
241 #[inline]
242 fn into_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {
243 self
244 }
245
246}
247
248impl<M: Model> Debug for Class<M> {
249 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
250 f.debug_struct("Class").field("name", &self.name).finish_non_exhaustive()
251 }
252}