use std::any::Any;
use hitbox_core::{BoxContext, CacheContext, CacheStatus, Context, ReadMode, ResponseSource};
use smallbox::smallbox;
use super::CompositionFormat;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CompositionLayer {
L1,
L2,
}
pub struct CompositionContext {
inner: BoxContext,
pub layer: CompositionLayer,
pub format: CompositionFormat,
}
impl CompositionContext {
pub fn wrap(inner: BoxContext, layer: CompositionLayer, format: CompositionFormat) -> Self {
Self {
inner,
layer,
format,
}
}
pub fn should_refill(&self) -> bool {
matches!(self.layer, CompositionLayer::L2)
}
pub fn inner(&self) -> &BoxContext {
&self.inner
}
}
impl Context for CompositionContext {
fn status(&self) -> CacheStatus {
self.inner.status()
}
fn set_status(&mut self, status: CacheStatus) {
self.inner.set_status(status);
}
fn source(&self) -> &ResponseSource {
self.inner.source()
}
fn set_source(&mut self, source: ResponseSource) {
self.inner.set_source(source);
}
fn read_mode(&self) -> ReadMode {
if self.should_refill() {
ReadMode::Refill
} else {
ReadMode::Direct
}
}
fn set_read_mode(&mut self, mode: ReadMode) {
self.inner.set_read_mode(mode);
}
fn as_any(&self) -> &dyn Any {
self
}
fn clone_box(&self) -> BoxContext {
smallbox!(CompositionContext {
inner: self.inner.clone_box(),
layer: self.layer,
format: self.format.clone(),
})
}
fn into_cache_context(self: Box<Self>) -> CacheContext {
hitbox_core::finalize_context(self.inner)
}
}
impl std::fmt::Debug for CompositionContext {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CompositionContext")
.field("layer", &self.layer)
.field("read_mode", &self.read_mode())
.finish()
}
}
pub fn upgrade_context(ctx: &mut BoxContext, layer: CompositionLayer, format: CompositionFormat) {
let inner = std::mem::replace(ctx, CacheContext::default().boxed());
*ctx = smallbox!(CompositionContext::wrap(inner, layer, format));
}