use std::ops::RangeBounds;
use crate::{
calculate_range,
context::BaseContext,
hostcalls::{self, BufferType},
log_concern,
property::envoy::Attributes,
};
pub trait StreamControl {
fn attributes(&self) -> &Attributes;
fn resume_downstream(&self) {
log_concern("resume-downstream", hostcalls::resume_downstream());
}
fn close_downstream(&self) {
log_concern("close-downstream", hostcalls::close_downstream());
}
fn resume_upstream(&self) {
log_concern("resume-upstream", hostcalls::resume_upstream());
}
fn close_upstream(&self) {
log_concern("close-upstream", hostcalls::close_upstream());
}
}
pub trait StreamDataControl {
const TYPE: StreamType;
fn data_size(&self) -> usize;
fn end_of_stream(&self) -> bool;
fn all(&self) -> Option<Vec<u8>> {
self.get(..)
}
fn get(&self, range: impl RangeBounds<usize>) -> Option<Vec<u8>> {
let (start, size) = calculate_range(range, self.data_size());
log_concern(
Self::TYPE.get(),
hostcalls::get_buffer(Self::TYPE.buffer(), start, size),
)
}
fn set(&self, range: impl RangeBounds<usize>, value: &[u8]) {
let (start, size) = calculate_range(range, self.data_size());
log_concern(
Self::TYPE.set(),
hostcalls::set_buffer(Self::TYPE.buffer(), start, size, value),
);
}
fn replace(&self, value: &[u8]) {
self.set(.., value);
}
fn clear(&self) {
self.replace(&[]);
}
#[cfg(not(target_arch = "wasm32"))]
fn write_upstream(&self, data: &[u8]) {
log_concern("write_upstream", hostcalls::write_upstream(data));
}
#[cfg(not(target_arch = "wasm32"))]
fn write_downstream(&self, data: &[u8]) {
log_concern("write_downstream", hostcalls::write_downstream(data));
}
}
#[repr(usize)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
#[non_exhaustive]
pub enum FilterStreamStatus {
Continue = 0,
StopIteration = 1,
}
#[derive(Debug)]
pub enum StreamType {
Upstream,
Downstream,
}
impl StreamType {
const fn get(&self) -> &'static str {
match self {
Self::Upstream => "get-upstream-data",
Self::Downstream => "get-downstream-data",
}
}
const fn set(&self) -> &'static str {
match self {
Self::Upstream => "set-upstream-data",
Self::Downstream => "set-downstream-data",
}
}
const fn buffer(&self) -> BufferType {
match self {
Self::Upstream => BufferType::UpstreamData,
Self::Downstream => BufferType::DownstreamData,
}
}
}
pub struct UpstreamData {
pub(crate) data_size: usize,
pub(crate) end_of_stream: bool,
pub(crate) attributes: Attributes,
}
impl StreamControl for UpstreamData {
fn attributes(&self) -> &Attributes {
&self.attributes
}
}
impl StreamDataControl for UpstreamData {
const TYPE: StreamType = StreamType::Upstream;
fn data_size(&self) -> usize {
self.data_size
}
fn end_of_stream(&self) -> bool {
self.end_of_stream
}
}
pub struct DownstreamData {
pub(crate) data_size: usize,
pub(crate) end_of_stream: bool,
pub(crate) attributes: Attributes,
}
impl StreamControl for DownstreamData {
fn attributes(&self) -> &Attributes {
&self.attributes
}
}
impl StreamDataControl for DownstreamData {
const TYPE: StreamType = StreamType::Downstream;
fn data_size(&self) -> usize {
self.data_size
}
fn end_of_stream(&self) -> bool {
self.end_of_stream
}
}
#[repr(usize)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
#[non_exhaustive]
pub enum CloseType {
Unknown = 0,
Local = 1,
Remote = 2,
}
pub struct StreamClose {
pub(crate) close_type: CloseType,
pub(crate) attributes: Attributes,
}
impl StreamClose {
pub fn close_type(&self) -> CloseType {
self.close_type
}
}
impl StreamControl for StreamClose {
fn attributes(&self) -> &Attributes {
&self.attributes
}
}
#[allow(unused_variables)]
pub trait StreamContext: BaseContext {
fn on_new_connection(&mut self) -> FilterStreamStatus {
FilterStreamStatus::Continue
}
fn on_downstream_data(&mut self, data: &DownstreamData) -> FilterStreamStatus {
FilterStreamStatus::Continue
}
fn on_downstream_close(&mut self, data: &StreamClose) {}
fn on_upstream_data(&mut self, data: &UpstreamData) -> FilterStreamStatus {
FilterStreamStatus::Continue
}
fn on_upstream_close(&mut self, data: &StreamClose) {}
}