use crate::error::{CaError, CaResult};
pub const DBR_STRING: u16 = 0;
pub const DBR_SHORT: u16 = 1;
pub const DBR_FLOAT: u16 = 2;
pub const DBR_ENUM: u16 = 3;
pub const DBR_CHAR: u16 = 4;
pub const DBR_LONG: u16 = 5;
pub const DBR_DOUBLE: u16 = 6;
pub const DBR_INT: u16 = DBR_SHORT;
pub const DBR_STS_STRING: u16 = 7;
pub const DBR_STS_SHORT: u16 = 8;
pub const DBR_STS_FLOAT: u16 = 9;
pub const DBR_STS_ENUM: u16 = 10;
pub const DBR_STS_CHAR: u16 = 11;
pub const DBR_STS_LONG: u16 = 12;
pub const DBR_STS_DOUBLE: u16 = 13;
pub const DBR_STS_INT: u16 = DBR_STS_SHORT;
pub const DBR_TIME_STRING: u16 = 14;
pub const DBR_TIME_SHORT: u16 = 15;
pub const DBR_TIME_FLOAT: u16 = 16;
pub const DBR_TIME_ENUM: u16 = 17;
pub const DBR_TIME_CHAR: u16 = 18;
pub const DBR_TIME_LONG: u16 = 19;
pub const DBR_TIME_DOUBLE: u16 = 20;
pub const DBR_TIME_INT: u16 = DBR_TIME_SHORT;
pub const DBR_GR_STRING: u16 = 21;
pub const DBR_GR_SHORT: u16 = 22;
pub const DBR_GR_FLOAT: u16 = 23;
pub const DBR_GR_ENUM: u16 = 24;
pub const DBR_GR_CHAR: u16 = 25;
pub const DBR_GR_LONG: u16 = 26;
pub const DBR_GR_DOUBLE: u16 = 27;
pub const DBR_GR_INT: u16 = DBR_GR_SHORT;
pub const DBR_CTRL_STRING: u16 = 28;
pub const DBR_CTRL_SHORT: u16 = 29;
pub const DBR_CTRL_FLOAT: u16 = 30;
pub const DBR_CTRL_ENUM: u16 = 31;
pub const DBR_CTRL_CHAR: u16 = 32;
pub const DBR_CTRL_LONG: u16 = 33;
pub const DBR_CTRL_DOUBLE: u16 = 34;
pub const DBR_CTRL_INT: u16 = DBR_CTRL_SHORT;
pub const DBR_PUT_ACKT: u16 = 35;
pub const DBR_PUT_ACKS: u16 = 36;
pub const DBR_STSACK_STRING: u16 = 37;
pub const DBR_CLASS_NAME: u16 = 38;
pub const LAST_BUFFER_TYPE: u16 = DBR_CLASS_NAME;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u16)]
pub enum DbFieldType {
String = 0,
Short = 1, Float = 2,
Enum = 3,
Char = 4, Long = 5, Double = 6,
Int64 = 7,
}
impl DbFieldType {
pub fn from_u16(v: u16) -> CaResult<Self> {
match v {
0 => Ok(Self::String),
1 => Ok(Self::Short),
2 => Ok(Self::Float),
3 => Ok(Self::Enum),
4 => Ok(Self::Char),
5 => Ok(Self::Long),
6 => Ok(Self::Double),
_ => Err(CaError::UnsupportedType(v)),
}
}
pub fn element_size(&self) -> usize {
match self {
Self::String => 40, Self::Short | Self::Enum => 2,
Self::Float | Self::Long => 4,
Self::Char => 1,
Self::Double | Self::Int64 => 8,
}
}
fn ca_wire_type(&self) -> u16 {
match self {
Self::Int64 => Self::Double as u16,
other => *other as u16,
}
}
pub fn sts_dbr_type(&self) -> u16 {
self.ca_wire_type() + 7
}
pub fn time_dbr_type(&self) -> u16 {
self.ca_wire_type() + 14
}
pub fn gr_dbr_type(&self) -> u16 {
self.ca_wire_type() + 21
}
pub fn ctrl_dbr_type(&self) -> u16 {
self.ca_wire_type() + 28
}
pub fn buffer_size(&self, count: usize) -> usize {
self.element_size() * count
}
pub fn to_dbr_type(&self) -> DbFieldType {
*self
}
}
pub fn dbr_buffer_size(dbr_type: u16, native_type: DbFieldType, count: usize) -> usize {
let value_size = native_type.element_size() * count;
let meta_size = match dbr_type / 7 {
0 => 0, 1 => 4, 2 => 12, 3 => {
match native_type {
DbFieldType::String => 4,
DbFieldType::Enum => 4 + 16 * 26, _ => 4 + 8 + 16 + 8 * 6, }
}
4 => {
match native_type {
DbFieldType::String => 4,
DbFieldType::Enum => 4 + 16 * 26,
_ => 4 + 8 + 16 + 8 * 8, }
}
_ => 0,
};
if dbr_type == DBR_CLASS_NAME {
return 40;
}
meta_size + value_size
}
fn dbr_native_index(dbr_type: u16) -> Option<u16> {
match dbr_type {
0..=6 => Some(dbr_type),
7..=13 => Some(dbr_type - 7),
14..=20 => Some(dbr_type - 14),
21..=27 => Some(dbr_type - 21),
28..=34 => Some(dbr_type - 28),
35 | 36 => Some(1), 37 => Some(0), 38 => Some(0),
_ => None,
}
}
pub fn native_type_for_dbr(dbr_type: u16) -> CaResult<DbFieldType> {
match dbr_native_index(dbr_type) {
Some(idx) => DbFieldType::from_u16(idx),
None => Err(CaError::UnsupportedType(dbr_type)),
}
}