1use super::{EpicsEnum, EpicsString, FieldId};
2use std::{fmt::Debug, mem::MaybeUninit, ptr};
3
4pub unsafe trait Field: Copy + Send + Sized + 'static + Debug {
10 type Raw: Copy + Send + Sized + 'static;
12 const ID: FieldId;
14
15 type StsRaw: Copy + Send + Sized + 'static;
16 type TimeRaw: Copy + Send + Sized + 'static;
17 type GrRaw: Copy + Send + Sized + 'static;
18 type CtrlRaw: Copy + Send + Sized + 'static;
19
20 type __StsPad: Copy + Send + Sized + 'static + Debug;
21 type __TimePad: Copy + Send + Sized + 'static + Debug;
22 type __GrPad: Copy + Send + Sized + 'static + Debug;
23 type __CtrlPad: Copy + Send + Sized + 'static + Debug;
24}
25pub trait Int: Field {}
27pub trait Float: Field {}
29
30unsafe impl Field for u8 {
31 type Raw = u8;
32 const ID: FieldId = FieldId::Char;
33
34 type StsRaw = sys::dbr_sts_char;
35 type TimeRaw = sys::dbr_time_char;
36 type GrRaw = sys::dbr_gr_char;
37 type CtrlRaw = sys::dbr_ctrl_char;
38
39 type __StsPad = [MaybeUninit<u8>; 1];
40 type __TimePad = [MaybeUninit<u8>; 3];
41 type __GrPad = [MaybeUninit<u8>; 1];
42 type __CtrlPad = [MaybeUninit<u8>; 1];
43}
44impl Int for u8 {}
45
46unsafe impl Field for i16 {
47 type Raw = i16;
48 const ID: FieldId = FieldId::Short;
49
50 type StsRaw = sys::dbr_sts_short;
51 type TimeRaw = sys::dbr_time_short;
52 type GrRaw = sys::dbr_gr_short;
53 type CtrlRaw = sys::dbr_ctrl_short;
54
55 type __StsPad = ();
56 type __TimePad = [MaybeUninit<u8>; 2];
57 type __GrPad = ();
58 type __CtrlPad = ();
59}
60impl Int for i16 {}
61
62unsafe impl Field for EpicsEnum {
63 type Raw = u16;
64 const ID: FieldId = FieldId::Enum;
65
66 type StsRaw = sys::dbr_sts_enum;
67 type TimeRaw = sys::dbr_time_enum;
68 type GrRaw = sys::dbr_gr_enum;
69 type CtrlRaw = sys::dbr_ctrl_enum;
70
71 type __StsPad = ();
72 type __TimePad = [MaybeUninit<u8>; 2];
73 type __GrPad = ();
74 type __CtrlPad = ();
75}
76
77unsafe impl Field for i32 {
78 type Raw = i32;
79 const ID: FieldId = FieldId::Long;
80
81 type StsRaw = sys::dbr_sts_long;
82 type TimeRaw = sys::dbr_time_long;
83 type GrRaw = sys::dbr_gr_long;
84 type CtrlRaw = sys::dbr_ctrl_long;
85
86 type __StsPad = ();
87 type __TimePad = ();
88 type __GrPad = ();
89 type __CtrlPad = ();
90}
91impl Int for i32 {}
92
93unsafe impl Field for f32 {
94 type Raw = f32;
95 const ID: FieldId = FieldId::Float;
96
97 type StsRaw = sys::dbr_sts_float;
98 type TimeRaw = sys::dbr_time_float;
99 type GrRaw = sys::dbr_gr_float;
100 type CtrlRaw = sys::dbr_ctrl_float;
101
102 type __StsPad = ();
103 type __TimePad = ();
104 type __GrPad = ();
105 type __CtrlPad = ();
106}
107impl Float for f32 {}
108
109unsafe impl Field for f64 {
110 type Raw = f64;
111 const ID: FieldId = FieldId::Double;
112
113 type StsRaw = sys::dbr_sts_double;
114 type TimeRaw = sys::dbr_time_double;
115 type GrRaw = sys::dbr_gr_double;
116 type CtrlRaw = sys::dbr_ctrl_double;
117
118 type __StsPad = [MaybeUninit<u8>; 4];
119 type __TimePad = [MaybeUninit<u8>; 4];
120 type __GrPad = ();
121 type __CtrlPad = ();
122}
123impl Float for f64 {}
124
125unsafe impl Field for EpicsString {
126 type Raw = sys::epicsOldString;
127 const ID: FieldId = FieldId::String;
128
129 type StsRaw = sys::dbr_sts_string;
130 type TimeRaw = sys::dbr_time_string;
131 type GrRaw = sys::dbr_sts_string;
132 type CtrlRaw = sys::dbr_sts_string;
133
134 type __StsPad = ();
135 type __TimePad = ();
136 type __GrPad = ();
137 type __CtrlPad = ();
138}
139
140#[allow(clippy::len_without_is_empty)]
148pub unsafe trait Value: Send + 'static {
149 type Item: Field;
151
152 fn len(&self) -> usize;
154 #[must_use]
156 fn check_len(count: usize) -> bool;
157 fn cast_ptr(ptr: *const u8, len: usize) -> *const Self;
159}
160
161unsafe impl<T: Field> Value for T {
162 type Item = T;
163
164 fn len(&self) -> usize {
165 1
166 }
167 fn check_len(count: usize) -> bool {
168 count == 1
169 }
170 fn cast_ptr(ptr: *const u8, _: usize) -> *const Self {
171 ptr as *const Self
172 }
173}
174
175unsafe impl<T: Field> Value for [T] {
176 type Item = T;
177
178 fn len(&self) -> usize {
179 self.len()
180 }
181 fn check_len(_: usize) -> bool {
182 true
183 }
184 fn cast_ptr(ptr: *const u8, len: usize) -> *const Self {
185 ptr::slice_from_raw_parts(ptr as *const T, len)
186 }
187}
188
189#[cfg(test)]
190mod tests {
191 use super::*;
192 use std::mem::{align_of, size_of};
193
194 fn assert_layout<T: Field>() {
195 assert_eq!(size_of::<T>(), size_of::<T::Raw>());
196 assert_eq!(align_of::<T>(), align_of::<T::Raw>());
197 }
198
199 #[test]
200 fn layout() {
201 assert_layout::<u8>();
202 assert_layout::<i16>();
203 assert_layout::<EpicsEnum>();
204 assert_layout::<i32>();
205 assert_layout::<f32>();
206 assert_layout::<f64>();
207 assert_layout::<EpicsString>();
208 }
209}