use std::rc::Rc;
use std::sync::atomic::{AtomicBool, AtomicI64};
use std::sync::Arc;
use super::{VmError, VmValue};
pub type VmJoinHandle = tokio::task::JoinHandle<Result<(VmValue, String), VmError>>;
pub struct VmTaskHandle {
pub handle: VmJoinHandle,
pub cancel_token: Arc<AtomicBool>,
}
#[derive(Debug, Clone)]
pub struct VmChannelHandle {
pub name: String,
pub sender: Arc<tokio::sync::mpsc::Sender<VmValue>>,
pub receiver: Arc<tokio::sync::Mutex<tokio::sync::mpsc::Receiver<VmValue>>>,
pub closed: Arc<AtomicBool>,
}
#[derive(Debug, Clone)]
pub struct VmAtomicHandle {
pub value: Arc<AtomicI64>,
}
#[derive(Debug, Clone, Copy)]
pub struct VmRange {
pub start: i64,
pub end: i64,
pub inclusive: bool,
}
impl VmRange {
pub fn len(&self) -> i64 {
if self.inclusive {
if self.start > self.end {
0
} else {
self.end.saturating_sub(self.start).saturating_add(1)
}
} else if self.start >= self.end {
0
} else {
self.end.saturating_sub(self.start)
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn get(&self, idx: i64) -> Option<i64> {
if idx < 0 || idx >= self.len() {
None
} else {
self.start.checked_add(idx)
}
}
pub fn first(&self) -> Option<i64> {
if self.is_empty() {
None
} else {
Some(self.start)
}
}
pub fn last(&self) -> Option<i64> {
if self.is_empty() {
None
} else if self.inclusive {
Some(self.end)
} else {
Some(self.end - 1)
}
}
pub fn contains(&self, v: i64) -> bool {
if self.is_empty() {
return false;
}
if self.inclusive {
v >= self.start && v <= self.end
} else {
v >= self.start && v < self.end
}
}
pub fn to_vec(&self) -> Vec<VmValue> {
let len = self.len();
if len <= 0 {
return Vec::new();
}
let cap = len as usize;
let mut out = Vec::with_capacity(cap);
for i in 0..len {
match self.start.checked_add(i) {
Some(v) => out.push(VmValue::Int(v)),
None => break,
}
}
out
}
}
#[derive(Debug, Clone)]
pub struct VmGenerator {
pub done: Rc<std::cell::Cell<bool>>,
pub receiver: Rc<tokio::sync::Mutex<tokio::sync::mpsc::Receiver<VmValue>>>,
}