use crate::error::{CaError, CaResult};
use crate::server::record::{FieldDesc, Record};
use crate::types::{DbFieldType, EpicsValue};
pub struct MbbiRecord {
pub val: u16,
pub nobt: i16,
pub zrsv: i16,
pub onsv: i16,
pub twsv: i16,
pub thsv: i16,
pub frsv: i16,
pub fvsv: i16,
pub sxsv: i16,
pub svsv: i16,
pub eisv: i16,
pub nisv: i16,
pub tesv: i16,
pub elsv: i16,
pub tvsv: i16,
pub ttsv: i16,
pub ftsv: i16,
pub ffsv: i16,
pub unsv: i16,
pub cosv: i16,
pub zrvl: i32,
pub onvl: i32,
pub twvl: i32,
pub thvl: i32,
pub frvl: i32,
pub fvvl: i32,
pub sxvl: i32,
pub svvl: i32,
pub eivl: i32,
pub nivl: i32,
pub tevl: i32,
pub elvl: i32,
pub tvvl: i32,
pub ttvl: i32,
pub ftvl: i32,
pub ffvl: i32,
pub zrst: String,
pub onst: String,
pub twst: String,
pub thst: String,
pub frst: String,
pub fvst: String,
pub sxst: String,
pub svst: String,
pub eist: String,
pub nist: String,
pub test: String,
pub elst: String,
pub tvst: String,
pub ttst: String,
pub ftst: String,
pub ffst: String,
}
impl Default for MbbiRecord {
fn default() -> Self {
Self {
val: 0,
nobt: 0,
zrsv: 0,
onsv: 0,
twsv: 0,
thsv: 0,
frsv: 0,
fvsv: 0,
sxsv: 0,
svsv: 0,
eisv: 0,
nisv: 0,
tesv: 0,
elsv: 0,
tvsv: 0,
ttsv: 0,
ftsv: 0,
ffsv: 0,
unsv: 0,
cosv: 0,
zrvl: 0,
onvl: 1,
twvl: 2,
thvl: 3,
frvl: 4,
fvvl: 5,
sxvl: 6,
svvl: 7,
eivl: 8,
nivl: 9,
tevl: 10,
elvl: 11,
tvvl: 12,
ttvl: 13,
ftvl: 14,
ffvl: 15,
zrst: String::new(),
onst: String::new(),
twst: String::new(),
thst: String::new(),
frst: String::new(),
fvst: String::new(),
sxst: String::new(),
svst: String::new(),
eist: String::new(),
nist: String::new(),
test: String::new(),
elst: String::new(),
tvst: String::new(),
ttst: String::new(),
ftst: String::new(),
ffst: String::new(),
}
}
}
impl MbbiRecord {
pub fn new(val: u16) -> Self {
Self {
val,
..Default::default()
}
}
fn raw_values(&self) -> [i32; 16] {
[
self.zrvl, self.onvl, self.twvl, self.thvl, self.frvl, self.fvvl, self.sxvl, self.svvl,
self.eivl, self.nivl, self.tevl, self.elvl, self.tvvl, self.ttvl, self.ftvl, self.ffvl,
]
}
fn raw_to_index(&self, raw: i32) -> Option<u16> {
let rvs = self.raw_values();
for (i, &rv) in rvs.iter().enumerate() {
if rv == raw {
return Some(i as u16);
}
}
None
}
}
static MBBI_FIELDS: &[FieldDesc] = &[
FieldDesc {
name: "VAL",
dbf_type: DbFieldType::Enum,
read_only: false,
},
FieldDesc {
name: "NOBT",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "ZRSV",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "ONSV",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "TWSV",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "THSV",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "FRSV",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "FVSV",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "SXSV",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "SVSV",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "EISV",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "NISV",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "TESV",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "ELSV",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "TVSV",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "TTSV",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "FTSV",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "FFSV",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "UNSV",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "COSV",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "ZRVL",
dbf_type: DbFieldType::Long,
read_only: false,
},
FieldDesc {
name: "ONVL",
dbf_type: DbFieldType::Long,
read_only: false,
},
FieldDesc {
name: "TWVL",
dbf_type: DbFieldType::Long,
read_only: false,
},
FieldDesc {
name: "THVL",
dbf_type: DbFieldType::Long,
read_only: false,
},
FieldDesc {
name: "FRVL",
dbf_type: DbFieldType::Long,
read_only: false,
},
FieldDesc {
name: "FVVL",
dbf_type: DbFieldType::Long,
read_only: false,
},
FieldDesc {
name: "SXVL",
dbf_type: DbFieldType::Long,
read_only: false,
},
FieldDesc {
name: "SVVL",
dbf_type: DbFieldType::Long,
read_only: false,
},
FieldDesc {
name: "EIVL",
dbf_type: DbFieldType::Long,
read_only: false,
},
FieldDesc {
name: "NIVL",
dbf_type: DbFieldType::Long,
read_only: false,
},
FieldDesc {
name: "TEVL",
dbf_type: DbFieldType::Long,
read_only: false,
},
FieldDesc {
name: "ELVL",
dbf_type: DbFieldType::Long,
read_only: false,
},
FieldDesc {
name: "TVVL",
dbf_type: DbFieldType::Long,
read_only: false,
},
FieldDesc {
name: "TTVL",
dbf_type: DbFieldType::Long,
read_only: false,
},
FieldDesc {
name: "FTVL",
dbf_type: DbFieldType::Long,
read_only: false,
},
FieldDesc {
name: "FFVL",
dbf_type: DbFieldType::Long,
read_only: false,
},
FieldDesc {
name: "ZRST",
dbf_type: DbFieldType::String,
read_only: false,
},
FieldDesc {
name: "ONST",
dbf_type: DbFieldType::String,
read_only: false,
},
FieldDesc {
name: "TWST",
dbf_type: DbFieldType::String,
read_only: false,
},
FieldDesc {
name: "THST",
dbf_type: DbFieldType::String,
read_only: false,
},
FieldDesc {
name: "FRST",
dbf_type: DbFieldType::String,
read_only: false,
},
FieldDesc {
name: "FVST",
dbf_type: DbFieldType::String,
read_only: false,
},
FieldDesc {
name: "SXST",
dbf_type: DbFieldType::String,
read_only: false,
},
FieldDesc {
name: "SVST",
dbf_type: DbFieldType::String,
read_only: false,
},
FieldDesc {
name: "EIST",
dbf_type: DbFieldType::String,
read_only: false,
},
FieldDesc {
name: "NIST",
dbf_type: DbFieldType::String,
read_only: false,
},
FieldDesc {
name: "TEST",
dbf_type: DbFieldType::String,
read_only: false,
},
FieldDesc {
name: "ELST",
dbf_type: DbFieldType::String,
read_only: false,
},
FieldDesc {
name: "TVST",
dbf_type: DbFieldType::String,
read_only: false,
},
FieldDesc {
name: "TTST",
dbf_type: DbFieldType::String,
read_only: false,
},
FieldDesc {
name: "FTST",
dbf_type: DbFieldType::String,
read_only: false,
},
FieldDesc {
name: "FFST",
dbf_type: DbFieldType::String,
read_only: false,
},
];
macro_rules! mbb_get_field {
($self:expr, $name:expr, $( $str:literal => $field:ident : $variant:ident ),* $(,)?) => {
match $name {
"VAL" => Some(EpicsValue::Enum($self.val)),
$( $str => Some(EpicsValue::$variant($self.$field.clone())), )*
_ => None,
}
};
}
macro_rules! mbb_put_field {
($self:expr, $name:expr, $value:expr, $( $str:literal => $field:ident : $variant:ident ),* $(,)?) => {
match $name {
"VAL" => {
match $value {
EpicsValue::Enum(v) => { $self.val = v; }
EpicsValue::Long(v) => { $self.val = v as u16; }
EpicsValue::Short(v) => { $self.val = v as u16; }
_ => return Err(CaError::TypeMismatch("VAL".into())),
}
}
$( $str => {
if let EpicsValue::$variant(v) = $value {
$self.$field = v;
} else {
return Err(CaError::TypeMismatch($str.into()));
}
} )*
_ => return Err(CaError::FieldNotFound($name.to_string())),
}
};
}
impl Record for MbbiRecord {
fn record_type(&self) -> &'static str {
"mbbi"
}
fn field_list(&self) -> &'static [FieldDesc] {
MBBI_FIELDS
}
fn get_field(&self, name: &str) -> Option<EpicsValue> {
mbb_get_field!(self, name,
"NOBT" => nobt: Short,
"ZRSV" => zrsv: Short, "ONSV" => onsv: Short, "TWSV" => twsv: Short, "THSV" => thsv: Short,
"FRSV" => frsv: Short, "FVSV" => fvsv: Short, "SXSV" => sxsv: Short, "SVSV" => svsv: Short,
"EISV" => eisv: Short, "NISV" => nisv: Short, "TESV" => tesv: Short, "ELSV" => elsv: Short,
"TVSV" => tvsv: Short, "TTSV" => ttsv: Short, "FTSV" => ftsv: Short, "FFSV" => ffsv: Short,
"UNSV" => unsv: Short, "COSV" => cosv: Short,
"ZRVL" => zrvl: Long, "ONVL" => onvl: Long, "TWVL" => twvl: Long, "THVL" => thvl: Long,
"FRVL" => frvl: Long, "FVVL" => fvvl: Long, "SXVL" => sxvl: Long, "SVVL" => svvl: Long,
"EIVL" => eivl: Long, "NIVL" => nivl: Long, "TEVL" => tevl: Long, "ELVL" => elvl: Long,
"TVVL" => tvvl: Long, "TTVL" => ttvl: Long, "FTVL" => ftvl: Long, "FFVL" => ffvl: Long,
"ZRST" => zrst: String, "ONST" => onst: String, "TWST" => twst: String, "THST" => thst: String,
"FRST" => frst: String, "FVST" => fvst: String, "SXST" => sxst: String, "SVST" => svst: String,
"EIST" => eist: String, "NIST" => nist: String, "TEST" => test: String, "ELST" => elst: String,
"TVST" => tvst: String, "TTST" => ttst: String, "FTST" => ftst: String, "FFST" => ffst: String,
)
}
fn put_field(&mut self, name: &str, value: EpicsValue) -> CaResult<()> {
mbb_put_field!(self, name, value,
"NOBT" => nobt: Short,
"ZRSV" => zrsv: Short, "ONSV" => onsv: Short, "TWSV" => twsv: Short, "THSV" => thsv: Short,
"FRSV" => frsv: Short, "FVSV" => fvsv: Short, "SXSV" => sxsv: Short, "SVSV" => svsv: Short,
"EISV" => eisv: Short, "NISV" => nisv: Short, "TESV" => tesv: Short, "ELSV" => elsv: Short,
"TVSV" => tvsv: Short, "TTSV" => ttsv: Short, "FTSV" => ftsv: Short, "FFSV" => ffsv: Short,
"UNSV" => unsv: Short, "COSV" => cosv: Short,
"ZRVL" => zrvl: Long, "ONVL" => onvl: Long, "TWVL" => twvl: Long, "THVL" => thvl: Long,
"FRVL" => frvl: Long, "FVVL" => fvvl: Long, "SXVL" => sxvl: Long, "SVVL" => svvl: Long,
"EIVL" => eivl: Long, "NIVL" => nivl: Long, "TEVL" => tevl: Long, "ELVL" => elvl: Long,
"TVVL" => tvvl: Long, "TTVL" => ttvl: Long, "FTVL" => ftvl: Long, "FFVL" => ffvl: Long,
"ZRST" => zrst: String, "ONST" => onst: String, "TWST" => twst: String, "THST" => thst: String,
"FRST" => frst: String, "FVST" => fvst: String, "SXST" => sxst: String, "SVST" => svst: String,
"EIST" => eist: String, "NIST" => nist: String, "TEST" => test: String, "ELST" => elst: String,
"TVST" => tvst: String, "TTST" => ttst: String, "FTST" => ftst: String, "FFST" => ffst: String,
);
Ok(())
}
fn set_val(&mut self, value: EpicsValue) -> CaResult<()> {
let raw = match value {
EpicsValue::Long(v) => v,
EpicsValue::Short(v) => v as i32,
EpicsValue::Enum(v) => {
self.val = v;
return Ok(());
}
_ => return Err(CaError::TypeMismatch("VAL".into())),
};
if let Some(idx) = self.raw_to_index(raw) {
self.val = idx;
} else {
self.val = raw as u16;
}
Ok(())
}
}