use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering};
use std::sync::Arc;
use std::time::SystemTime;
use crate::error::AsynStatus;
#[derive(Debug, Clone)]
pub enum RequestOp {
OctetWrite { data: Vec<u8> },
OctetRead { buf_size: usize },
OctetWriteRead { data: Vec<u8>, buf_size: usize },
Int32Write { value: i32 },
Int32Read,
Int64Write { value: i64 },
Int64Read,
Float64Write { value: f64 },
Float64Read,
UInt32DigitalWrite { value: u32, mask: u32 },
UInt32DigitalRead { mask: u32 },
Flush,
Connect,
Disconnect,
BlockProcess,
UnblockProcess,
DrvUserCreate { drv_info: String },
EnumRead,
EnumWrite { index: usize },
Int32ArrayRead { max_elements: usize },
Int32ArrayWrite { data: Vec<i32> },
Float64ArrayRead { max_elements: usize },
Float64ArrayWrite { data: Vec<f64> },
CallParamCallbacks { addr: i32 },
GetOption { key: String },
SetOption { key: String, value: String },
}
#[derive(Debug)]
pub struct RequestResult {
pub status: AsynStatus,
pub message: String,
pub nbytes: usize,
pub data: Option<Vec<u8>>,
pub int_val: Option<i32>,
pub int64_val: Option<i64>,
pub float_val: Option<f64>,
pub uint_val: Option<u32>,
pub reason: Option<usize>,
pub enum_index: Option<usize>,
pub int32_array: Option<Vec<i32>>,
pub float64_array: Option<Vec<f64>>,
pub alarm_status: u16,
pub alarm_severity: u16,
pub timestamp: Option<SystemTime>,
pub option_value: Option<String>,
}
impl RequestResult {
fn base() -> Self {
Self {
status: AsynStatus::Success,
message: String::new(),
nbytes: 0,
data: None,
int_val: None,
int64_val: None,
float_val: None,
uint_val: None,
reason: None,
enum_index: None,
int32_array: None,
float64_array: None,
alarm_status: 0,
alarm_severity: 0,
timestamp: None,
option_value: None,
}
}
pub fn write_ok() -> Self {
Self::base()
}
pub fn octet_read(buf: Vec<u8>, nbytes: usize) -> Self {
Self { nbytes, data: Some(buf), ..Self::base() }
}
pub fn int32_read(value: i32) -> Self {
Self { int_val: Some(value), ..Self::base() }
}
pub fn int64_read(value: i64) -> Self {
Self { int64_val: Some(value), ..Self::base() }
}
pub fn float64_read(value: f64) -> Self {
Self { float_val: Some(value), ..Self::base() }
}
pub fn uint32_read(value: u32) -> Self {
Self { uint_val: Some(value), ..Self::base() }
}
pub fn drv_user_create(reason: usize) -> Self {
Self { reason: Some(reason), ..Self::base() }
}
pub fn enum_read(index: usize) -> Self {
Self { enum_index: Some(index), ..Self::base() }
}
pub fn int32_array_read(data: Vec<i32>) -> Self {
Self { int32_array: Some(data), ..Self::base() }
}
pub fn float64_array_read(data: Vec<f64>) -> Self {
Self { float64_array: Some(data), ..Self::base() }
}
pub fn option_read(value: String) -> Self {
Self { option_value: Some(value), ..Self::base() }
}
pub fn with_alarm(mut self, alarm_status: u16, alarm_severity: u16, timestamp: Option<SystemTime>) -> Self {
self.alarm_status = alarm_status;
self.alarm_severity = alarm_severity;
self.timestamp = timestamp;
self
}
}
#[derive(Clone, Debug)]
pub struct CancelToken(pub Arc<AtomicBool>);
impl CancelToken {
pub fn new() -> Self {
Self(Arc::new(AtomicBool::new(false)))
}
pub fn cancel(&self) {
self.0.store(true, AtomicOrdering::Release);
}
pub fn is_cancelled(&self) -> bool {
self.0.load(AtomicOrdering::Acquire)
}
}
impl Default for CancelToken {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn cancel_token() {
let token = CancelToken::new();
assert!(!token.is_cancelled());
token.cancel();
assert!(token.is_cancelled());
}
}