1use super::{ReadRequest, Request, WriteRequest};
2use crate::{
3 error::{self, Error},
4 types::*,
5};
6use derivative::Derivative;
7use std::{
8 alloc::{alloc, Layout},
9 mem::{size_of, MaybeUninit},
10 ptr,
11};
12
13pub const MAX_UNITS_SIZE: usize = sys::MAX_UNITS_SIZE as usize;
14pub const MAX_ENUM_STRING_SIZE: usize = sys::MAX_ENUM_STRING_SIZE as usize;
15pub const MAX_ENUM_STATES: usize = sys::MAX_ENUM_STATES as usize;
16
17#[repr(transparent)]
18#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
19pub struct Units(pub StaticCString<MAX_UNITS_SIZE>);
20
21pub trait TypedRequest: Request {
23 type Value: Value + ?Sized;
24
25 fn value(&self) -> &Self::Value;
26 fn value_mut(&mut self) -> &mut Self::Value;
27}
28
29macro_rules! impl_request_methods {
30 () => {
31 fn len(&self) -> usize {
32 self.value().len()
33 }
34 unsafe fn from_ptr<'a>(
35 ptr: *const u8,
36 dbr: RequestId,
37 count: usize,
38 ) -> Result<&'a Self, Error> {
39 if dbr != Self::ID {
40 Err(error::BADTYPE)
41 } else if !V::check_len(count) {
42 Err(error::BADCOUNT)
43 } else {
44 Ok(&*(V::cast_ptr(ptr, count) as *const Self))
45 }
46 }
47 fn clone_boxed(&self) -> Box<Self> {
48 unsafe {
49 let ptr = alloc(Layout::for_value(self));
50 let size = size_of::<Self::Raw>()
51 + size_of::<V::Item>() * (if self.len() == 0 { 0 } else { self.len() - 1 });
52 ptr::copy_nonoverlapping(self as *const _ as *const u8, ptr, size);
53 let this_ptr = V::cast_ptr(ptr, self.len()) as *mut Self;
54 Box::from_raw(this_ptr)
55 }
56 }
57 };
58}
59macro_rules! impl_typed_request {
60 () => {
61 type Value = V;
62
63 fn value(&self) -> &Self::Value {
64 &self.value
65 }
66 fn value_mut(&mut self) -> &mut Self::Value {
67 &mut self.value
68 }
69 };
70}
71
72unsafe impl<V: Value + ?Sized> Request for V {
73 type Raw = <V::Item as Field>::Raw;
74 const ID: RequestId = RequestId::Base(<V::Item as Field>::ID);
75 impl_request_methods!();
76}
77impl<V: Value + ?Sized> TypedRequest for V {
78 type Value = V;
79 fn value(&self) -> &V {
80 self
81 }
82 fn value_mut(&mut self) -> &mut V {
83 self
84 }
85}
86impl<V: Value + ?Sized> ReadRequest for V {}
87impl<V: Value + ?Sized> WriteRequest for V {}
88
89#[repr(C)]
90#[derive(Clone, Copy, Derivative)]
91#[derivative(Debug)]
92pub struct Sts<V: Value + ?Sized> {
93 pub alarm: Alarm,
94 #[derivative(Debug = "ignore")]
95 _value_padding: <V::Item as Field>::__StsPad,
96 pub value: V,
97}
98unsafe impl<V: Value + ?Sized> Request for Sts<V> {
99 type Raw = <V::Item as Field>::StsRaw;
100 const ID: RequestId = RequestId::Sts(<V::Item as Field>::ID);
101 impl_request_methods!();
102}
103impl<V: Value + ?Sized> TypedRequest for Sts<V> {
104 impl_typed_request!();
105}
106impl<V: Value + ?Sized> ReadRequest for Sts<V> {}
107
108#[repr(C)]
109#[derive(Clone, Copy, Derivative)]
110#[derivative(Debug)]
111pub struct StsackString<V: Value<Item = EpicsString> + ?Sized> {
112 pub alarm: Alarm,
113 pub ackt: u16,
114 pub acks: u16,
115 pub value: V,
116}
117unsafe impl<V: Value<Item = EpicsString> + ?Sized> Request for StsackString<V> {
118 type Raw = sys::dbr_stsack_string;
119 const ID: RequestId = RequestId::StsackString;
120 impl_request_methods!();
121}
122impl<V: Value<Item = EpicsString> + ?Sized> TypedRequest for StsackString<V> {
123 impl_typed_request!();
124}
125impl<V: Value<Item = EpicsString> + ?Sized> ReadRequest for StsackString<V> {}
126
127#[repr(C)]
128#[derive(Clone, Copy, Derivative)]
129#[derivative(Debug)]
130pub struct Time<V: Value + ?Sized> {
131 pub alarm: Alarm,
132 pub stamp: EpicsTimeStamp,
133 #[derivative(Debug = "ignore")]
134 _value_padding: <V::Item as Field>::__TimePad,
135 pub value: V,
136}
137unsafe impl<V: Value + ?Sized> Request for Time<V> {
138 type Raw = <V::Item as Field>::TimeRaw;
139 const ID: RequestId = RequestId::Time(<V::Item as Field>::ID);
140 impl_request_methods!();
141}
142impl<V: Value + ?Sized> TypedRequest for Time<V> {
143 impl_typed_request!();
144}
145impl<V: Value + ?Sized> ReadRequest for Time<V> {}
146
147#[repr(C)]
148#[derive(Clone, Copy, Derivative)]
149#[derivative(Debug)]
150pub struct GrInt<V: Value + ?Sized>
151where
152 V::Item: Int,
153{
154 pub alarm: Alarm,
155 pub units: Units,
156 pub upper_disp_limit: V::Item,
157 pub lower_disp_limit: V::Item,
158 pub upper_alarm_limit: V::Item,
159 pub upper_warning_limit: V::Item,
160 pub lower_warning_limit: V::Item,
161 pub lower_alarm_limit: V::Item,
162 #[derivative(Debug = "ignore")]
163 _value_padding: <V::Item as Field>::__GrPad,
164 pub value: V,
165}
166unsafe impl<V: Value + ?Sized> Request for GrInt<V>
167where
168 V::Item: Int,
169{
170 type Raw = <V::Item as Field>::GrRaw;
171 const ID: RequestId = RequestId::Gr(<V::Item as Field>::ID);
172 impl_request_methods!();
173}
174impl<V: Value + ?Sized> TypedRequest for GrInt<V>
175where
176 V::Item: Int,
177{
178 impl_typed_request!();
179}
180impl<V: Value + ?Sized> ReadRequest for GrInt<V> where V::Item: Int {}
181
182#[repr(C)]
183#[derive(Clone, Copy, Derivative)]
184#[derivative(Debug)]
185pub struct GrFloat<V: Value + ?Sized>
186where
187 V::Item: Float,
188{
189 pub alarm: Alarm,
190 pub precision: i16,
191 #[derivative(Debug = "ignore")]
192 _units_padding: [MaybeUninit<u8>; 2],
193 pub units: Units,
194 pub upper_disp_limit: V::Item,
195 pub lower_disp_limit: V::Item,
196 pub upper_alarm_limit: V::Item,
197 pub upper_warning_limit: V::Item,
198 pub lower_warning_limit: V::Item,
199 pub lower_alarm_limit: V::Item,
200 #[derivative(Debug = "ignore")]
201 _value_padding: <V::Item as Field>::__GrPad,
202 pub value: V,
203}
204unsafe impl<V: Value + ?Sized> Request for GrFloat<V>
205where
206 V::Item: Float,
207{
208 type Raw = <V::Item as Field>::GrRaw;
209 const ID: RequestId = RequestId::Gr(<V::Item as Field>::ID);
210 impl_request_methods!();
211}
212impl<V: Value + ?Sized> TypedRequest for GrFloat<V>
213where
214 V::Item: Float,
215{
216 impl_typed_request!();
217}
218impl<V: Value + ?Sized> ReadRequest for GrFloat<V> where V::Item: Float {}
219
220#[repr(C)]
221#[derive(Clone, Copy, Derivative)]
222#[derivative(Debug)]
223pub struct GrEnum<V: Value<Item = EpicsEnum> + ?Sized> {
224 pub alarm: Alarm,
225 pub no_str: u16,
226 pub strs: [StaticCString<MAX_ENUM_STRING_SIZE>; MAX_ENUM_STATES],
227 #[derivative(Debug = "ignore")]
228 _value_padding: <V::Item as Field>::__GrPad,
229 pub value: V,
230}
231unsafe impl<V: Value<Item = EpicsEnum> + ?Sized> Request for GrEnum<V> {
232 type Raw = <V::Item as Field>::GrRaw;
233 const ID: RequestId = RequestId::Sts(<V::Item as Field>::ID);
234 impl_request_methods!();
235}
236impl<V: Value<Item = EpicsEnum> + ?Sized> TypedRequest for GrEnum<V> {
237 impl_typed_request!();
238}
239impl<V: Value<Item = EpicsEnum> + ?Sized> ReadRequest for GrEnum<V> {}
240
241#[repr(C)]
242#[derive(Clone, Copy, Derivative)]
243#[derivative(Debug)]
244pub struct GrString<V: Value<Item = EpicsString> + ?Sized> {
245 pub alarm: Alarm,
246 #[derivative(Debug = "ignore")]
247 _value_padding: <V::Item as Field>::__GrPad,
248 pub value: V,
249}
250unsafe impl<V: Value<Item = EpicsString> + ?Sized> Request for GrString<V> {
251 type Raw = <V::Item as Field>::GrRaw;
252 const ID: RequestId = RequestId::Gr(<V::Item as Field>::ID);
253 impl_request_methods!();
254}
255impl<V: Value<Item = EpicsString> + ?Sized> TypedRequest for GrString<V> {
256 impl_typed_request!();
257}
258impl<V: Value<Item = EpicsString> + ?Sized> ReadRequest for GrString<V> {}
259
260#[repr(C)]
261#[derive(Clone, Copy, Derivative)]
262#[derivative(Debug)]
263pub struct CtrlInt<V: Value + ?Sized>
264where
265 V::Item: Int,
266{
267 pub alarm: Alarm,
268 pub units: Units,
269 pub upper_disp_limit: V::Item,
270 pub lower_disp_limit: V::Item,
271 pub upper_alarm_limit: V::Item,
272 pub upper_warning_limit: V::Item,
273 pub lower_warning_limit: V::Item,
274 pub lower_alarm_limit: V::Item,
275 pub upper_ctrl_limit: V::Item,
276 pub lower_ctrl_limit: V::Item,
277 #[derivative(Debug = "ignore")]
278 _value_padding: <V::Item as Field>::__CtrlPad,
279 pub value: V,
280}
281unsafe impl<V: Value + ?Sized> Request for CtrlInt<V>
282where
283 V::Item: Int,
284{
285 type Raw = <V::Item as Field>::CtrlRaw;
286 const ID: RequestId = RequestId::Ctrl(<V::Item as Field>::ID);
287 impl_request_methods!();
288}
289impl<V: Value + ?Sized> TypedRequest for CtrlInt<V>
290where
291 V::Item: Int,
292{
293 impl_typed_request!();
294}
295impl<V: Value + ?Sized> ReadRequest for CtrlInt<V> where V::Item: Int {}
296
297#[repr(C)]
298#[derive(Clone, Copy, Derivative)]
299#[derivative(Debug)]
300pub struct CtrlFloat<V: Value + ?Sized>
301where
302 V::Item: Float,
303{
304 pub alarm: Alarm,
305 pub precision: i16,
306 #[derivative(Debug = "ignore")]
307 _units_padding: MaybeUninit<u16>,
308 pub units: Units,
309 pub upper_disp_limit: V::Item,
310 pub lower_disp_limit: V::Item,
311 pub upper_alarm_limit: V::Item,
312 pub upper_warning_limit: V::Item,
313 pub lower_warning_limit: V::Item,
314 pub lower_alarm_limit: V::Item,
315 pub upper_ctrl_limit: V::Item,
316 pub lower_ctrl_limit: V::Item,
317 #[derivative(Debug = "ignore")]
318 _value_padding: <V::Item as Field>::__CtrlPad,
319 pub value: V,
320}
321unsafe impl<V: Value + ?Sized> Request for CtrlFloat<V>
322where
323 V::Item: Float,
324{
325 type Raw = <V::Item as Field>::CtrlRaw;
326 const ID: RequestId = RequestId::Ctrl(<V::Item as Field>::ID);
327 impl_request_methods!();
328}
329impl<V: Value + ?Sized> TypedRequest for CtrlFloat<V>
330where
331 V::Item: Float,
332{
333 impl_typed_request!();
334}
335impl<V: Value + ?Sized> ReadRequest for CtrlFloat<V> where V::Item: Float {}
336
337#[repr(C)]
338#[derive(Clone, Copy, Derivative)]
339#[derivative(Debug)]
340pub struct CtrlEnum<V: Value<Item = EpicsEnum> + ?Sized> {
341 pub alarm: Alarm,
342 pub no_str: u16,
343 pub strs: [StaticCString<MAX_ENUM_STRING_SIZE>; MAX_ENUM_STATES],
344 #[derivative(Debug = "ignore")]
345 _value_padding: <V::Item as Field>::__CtrlPad,
346 pub value: V,
347}
348unsafe impl<V: Value<Item = EpicsEnum> + ?Sized> Request for CtrlEnum<V> {
349 type Raw = <V::Item as Field>::CtrlRaw;
350 const ID: RequestId = RequestId::Sts(<V::Item as Field>::ID);
351 impl_request_methods!();
352}
353impl<V: Value<Item = EpicsEnum> + ?Sized> TypedRequest for CtrlEnum<V> {
354 impl_typed_request!();
355}
356impl<V: Value<Item = EpicsEnum> + ?Sized> ReadRequest for CtrlEnum<V> {}
357
358#[repr(C)]
359#[derive(Clone, Copy, Derivative)]
360#[derivative(Debug)]
361pub struct CtrlString<V: Value<Item = EpicsString> + ?Sized> {
362 pub alarm: Alarm,
363 #[derivative(Debug = "ignore")]
364 _value_padding: <V::Item as Field>::__CtrlPad,
365 pub value: V,
366}
367unsafe impl<V: Value<Item = EpicsString> + ?Sized> Request for CtrlString<V> {
368 type Raw = <V::Item as Field>::CtrlRaw;
369 const ID: RequestId = RequestId::Ctrl(<V::Item as Field>::ID);
370 impl_request_methods!();
371}
372impl<V: Value<Item = EpicsString> + ?Sized> TypedRequest for CtrlString<V> {
373 impl_typed_request!();
374}
375impl<V: Value<Item = EpicsString> + ?Sized> ReadRequest for CtrlString<V> {}