use std::collections::VecDeque;
use rquickjs::{class::Trace, Ctx, Exception, JsLifetime, Result, Value};
use crate::stream_web::queuing_strategy::SizeValue;
#[derive(JsLifetime, Trace, Default)]
pub struct QueueWithSizes<'js> {
pub queue: VecDeque<ValueWithSize<'js>>,
pub queue_total_size: f64,
}
impl<'js> QueueWithSizes<'js> {
pub fn new() -> Self {
Self {
queue: VecDeque::new(),
queue_total_size: 0.0,
}
}
pub(crate) fn enqueue_value_with_size(
&mut self,
ctx: &Ctx<'js>,
value: Value<'js>,
size: SizeValue<'js>,
) -> Result<()> {
let size = match is_non_negative_number(size) {
None => {
return Err(Exception::throw_range(
ctx,
"Size must be a finite, non-NaN, non-negative number.",
));
},
Some(size) => size,
};
if size.is_infinite() {
return Err(Exception::throw_range(
ctx,
"Size must be a finite, non-NaN, non-negative number.",
));
};
self.queue.push_back(ValueWithSize { value, size });
self.queue_total_size += size;
Ok(())
}
pub fn dequeue_value(&mut self) -> Value<'js> {
let value_with_size = self
.queue
.pop_front()
.expect("DequeueValue called with empty queue");
self.queue_total_size -= value_with_size.size;
if self.queue_total_size < 0.0 {
self.queue_total_size = 0.0
}
value_with_size.value
}
pub fn reset_queue(&mut self) {
self.queue.clear();
self.queue_total_size = 0.0;
}
}
#[derive(JsLifetime, Trace, Clone)]
pub struct ValueWithSize<'js> {
pub value: Value<'js>,
size: f64,
}
fn is_non_negative_number(value: SizeValue<'_>) -> Option<f64> {
let number = value.as_number()?;
if number.is_nan() {
return None;
}
if number < 0.0 {
return None;
}
Some(number)
}