epics_ca/request/
base.rs

1use crate::{
2    error::{self, Error},
3    types::{EpicsString, RequestId},
4};
5
6/// Abstract request to channel.
7///
8/// # Safety
9///
10/// Should be implemented only for requests supported by channel access.
11///
12/// `Self` and `Self::Raw` must be safely transmutable to each other.
13#[allow(clippy::len_without_is_empty)]
14pub unsafe trait Request: Send + 'static {
15    /// Raw request structure.
16    type Raw: Copy + Send + Sized + 'static;
17    /// Request identifier.
18    const ID: RequestId;
19
20    /// Length of the value in the request.
21    fn len(&self) -> usize;
22    /// Create reference (possibly wide) to the request from raw pointer and count of elements.
23    ///
24    /// # Safety
25    ///
26    /// Pointer must be valid and point to raw request structure.
27    unsafe fn from_ptr<'a>(ptr: *const u8, dbr: RequestId, count: usize)
28        -> Result<&'a Self, Error>;
29    /// Clone request and put it in newly allocated box.
30    fn clone_boxed(&self) -> Box<Self>;
31}
32
33macro_rules! impl_request_methods {
34    () => {
35        fn len(&self) -> usize {
36            1
37        }
38        unsafe fn from_ptr<'a>(
39            ptr: *const u8,
40            dbr: RequestId,
41            count: usize,
42        ) -> Result<&'a Self, Error> {
43            if dbr != Self::ID {
44                Err(error::BADTYPE)
45            } else if count != 1 {
46                Err(error::BADCOUNT)
47            } else {
48                Ok(&*(ptr as *const Self))
49            }
50        }
51        fn clone_boxed(&self) -> Box<Self> {
52            Box::new(*self)
53        }
54    };
55}
56
57/// Request that writes some data to channel.
58pub trait WriteRequest: Request {}
59/// Request that reads some data from channel.
60pub trait ReadRequest: Request {}
61
62#[repr(transparent)]
63#[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
64pub struct PutAckt(pub u16);
65
66unsafe impl Request for PutAckt {
67    type Raw = sys::dbr_put_ackt_t;
68    const ID: RequestId = RequestId::PutAckt;
69    impl_request_methods!();
70}
71impl WriteRequest for PutAckt {}
72
73#[repr(transparent)]
74#[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
75pub struct PutAcks(pub u16);
76
77unsafe impl Request for PutAcks {
78    type Raw = sys::dbr_put_acks_t;
79    const ID: RequestId = RequestId::PutAcks;
80    impl_request_methods!();
81}
82impl WriteRequest for PutAcks {}
83
84#[repr(transparent)]
85#[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
86pub struct ClassName(pub EpicsString);
87
88unsafe impl Request for ClassName {
89    type Raw = sys::dbr_class_name_t;
90    const ID: RequestId = RequestId::ClassName;
91    impl_request_methods!();
92}
93impl ReadRequest for ClassName {}