epics_ca/request/
typed.rs

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
21/// Request that stores value of specific type (along with optional metadata).
22pub 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> {}