1use std::sync::{Arc, Mutex, Weak};
4use std::collections::HashMap;
5use std::fmt::{self, Debug};
6use std::future::Future;
7
8use crate::dev::{All, Named, ToNames, ToNamesNotAll};
9use crate::database::{GetPropSpec, SetPropSpec};
10use crate::error::{Error, ErrorKind, Result};
11use crate::name::{ArcName, Name};
12use crate::value::Spectrum;
13
14use super::{reserved_name, Model, Ref, RESERVED_ATTRS};
15use super::dev::{AnyDev, Dev};
16use super::server::Server;
17use super::def::ClassDef;
18
19
20pub trait AnyClass: Debug + Send + Sync {
22
23 fn name(&self) -> &str;
25
26 fn index(&self) -> usize;
29
30 fn add_dev(&self, name: &str) -> Result<Arc<dyn AnyDev>>;
32
33}
34
35pub struct Class<M: Model> {
36 name: Arc<str>,
39 index: usize,
41 this: Weak<Self>,
43 server: Arc<Server>,
44 def: Arc<ClassDef<M>>,
45 attr_props: Mutex<HashMap<ArcName, Arc<[Named<Spectrum<str>>]>>>,
48}
49
50impl<M: Model> Class<M> {
51
52 pub(super) fn new(server: Arc<Server>, def: Arc<ClassDef<M>>, index: usize) -> Arc<Self> {
55 Arc::new_cyclic(|this| Self {
56 name: Arc::from(&*def.name),
57 index,
58 this: this.clone(),
59 server,
60 def,
61 attr_props: Mutex::new(HashMap::new()),
62 })
63 }
64
65 #[inline]
66 pub fn name(&self) -> &str {
67 &self.name
68 }
69
70 #[inline]
71 pub fn server(&self) -> &Server {
72 &self.server
73 }
74
75 pub async fn list_prop_async(&self, filter: &str) -> Result<Spectrum<str>> {
82 self.server().database().list_class_prop_async(&self.name, filter).await
83 }
84
85 pub fn list_prop(&self, filter: &str) -> Result<Spectrum<str>> {
87 self.server().database().list_class_prop(&self.name, filter)
88 }
89
90 pub fn get_prop_async<Spec, Names: ToNames>(&self, names: Names) -> impl Future<Output = Result<Spec::Output>> + Send
93 where
94 Spec: GetPropSpec<Names>,
95 {
96 self.server().database().get_class_prop_async::<Spec, Names>(&self.name, names)
97 }
98
99 pub fn get_prop<Spec, Names: ToNames>(&self, names: Names) -> Result<Spec::Output>
101 where
102 Spec: GetPropSpec<Names>,
103 {
104 self.server().database().get_class_prop::<Spec, Names>(&self.name, names)
105 }
106
107 pub fn set_prop_async<'a, Spec>(&'a self, spec: Spec) -> impl Future<Output = Result<()>> + Send
109 where
110 Spec: SetPropSpec<'a>,
111 {
112 self.server().database().set_class_prop_async(&self.name, spec)
113 }
114
115 pub fn set_prop<'a, Spec>(&'a self, spec: Spec) -> Result<()>
117 where
118 Spec: SetPropSpec<'a>,
119 {
120 self.server().database().set_class_prop(&self.name, spec)
121 }
122
123 pub fn del_prop_async<Names: ToNamesNotAll>(&self, names: Names) -> impl Future<Output = Result<()>> + Send {
125 self.server().database().del_class_prop_async(&self.name, names)
126 }
127
128 pub fn del_prop<Names: ToNamesNotAll>(&self, names: Names) -> Result<()> {
130 self.server().database().del_class_prop(&self.name, names)
131 }
132
133 pub(super) async fn attr_props(&self, names: &[&str]) -> Result<Vec<Arc<[Named<Spectrum<str>>]>>> {
144
145 let missing = {
147 let attr_props = self.attr_props.lock().unwrap();
148 names.iter()
149 .copied()
150 .filter(|name| !attr_props.contains_key(Name::new(name)))
151 .filter(|name| reserved_name(name, RESERVED_ATTRS).is_none())
152 .collect::<Vec<_>>()
153 };
154
155 if !missing.is_empty() {
156
157 let fetched = self.server()
158 .database()
159 .get_class_attr_prop_async::<Spectrum<str>, _, _>(&self.name, missing.as_slice(), All).await?;
160
161 let mut attr_props = self.attr_props.lock().unwrap();
162 for (name, props) in missing.into_iter().zip(fetched) {
163 attr_props.insert(ArcName::from(Arc::<str>::from(name)), Arc::from(props?));
164 }
165
166 }
167
168 let attr_props = self.attr_props.lock().unwrap();
169 Ok(names
170 .iter()
171 .map(|name| attr_props.get(Name::new(name))
172 .map_or_else(|| Arc::from([]), Arc::clone))
173 .collect())
174
175 }
176
177 #[inline]
178 pub fn def(&self) -> &ClassDef<M> {
179 &self.def
180 }
181
182 pub fn add_dev(&self, name: &str) -> Result<Ref<'_, Dev<M>>> {
187 self.new_dev(name).map(Ref::new)
188 }
189
190 fn new_dev(&self, name: &str) -> Result<Arc<Dev<M>>> {
192
193 let mut server_devs = self.server.devs.lock().unwrap();
194 if server_devs.contains_key(Name::new(name)) {
195 return Err(Error::new(ErrorKind::DevAlreadyDefined)
196 .with_append_description(format_args!("Device {name:?}")));
197 }
198
199 let name = Arc::<str>::from(name);
200 let dev = Dev::new(self.this.upgrade().unwrap(), Arc::clone(&name));
202 server_devs.insert(ArcName::from(name), Arc::clone(&dev) as Arc<dyn AnyDev>);
203 drop(server_devs);
204
205 self.server.pending.lock().unwrap().added.push(Arc::clone(&dev) as Arc<dyn AnyDev>);
206 Ok(dev)
207
208 }
209
210}
211
212impl<M: Model> AnyClass for Class<M> {
213
214 #[inline]
215 fn name(&self) -> &str {
216 &self.name
217 }
218
219 #[inline]
220 fn index(&self) -> usize {
221 self.index
222 }
223
224 fn add_dev(&self, name: &str) -> Result<Arc<dyn AnyDev>> {
225 self.new_dev(name).map(|dev| dev as Arc<dyn AnyDev>)
226 }
227
228}
229
230impl<M: Model> Debug for Class<M> {
231 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
232 f.debug_struct("Class").field("name", &self.name).finish_non_exhaustive()
233 }
234}