use crate::stable_with_metadata_of::WithMetadataOf;
use std::{
any::Any,
io::{Seek, Write},
};
pub struct Writer<W> {
inner: W,
write: *mut dyn Write,
vtable: OptTable,
}
#[derive(Clone, Copy)]
struct OptTable {
seek: Option<*mut dyn Seek>,
any: Option<*mut dyn Any>,
}
pub struct WriterMut<'lt> {
inner: &'lt mut dyn Write,
vtable: OptTable,
}
pub struct WriterBox<'lt> {
inner: Box<dyn Write + 'lt>,
vtable: OptTable,
}
impl<W: Write> Writer<W> {
pub fn new(mut writer: W) -> Self {
let write = lifetime_erase_trait_vtable!((&mut writer): '_ as Write);
Writer {
inner: writer,
write,
vtable: OptTable {
seek: None,
any: None,
},
}
}
}
impl<W> Writer<W> {
pub fn get_ref(&self) -> &W {
&self.inner
}
pub fn get_mut(&mut self) -> &mut W {
&mut self.inner
}
pub fn as_mut(&mut self) -> WriterMut<'_> {
let Writer {
inner: _,
write: _,
vtable,
} = *self;
WriterMut {
inner: self.as_write_mut(),
vtable,
}
}
pub fn into_boxed<'lt>(self) -> WriterBox<'lt>
where
W: 'lt,
{
let Writer {
inner,
write,
vtable,
} = self;
let ptr = Box::into_raw(Box::new(inner));
let ptr = WithMetadataOf::with_metadata_of_on_stable(ptr, write);
let inner = unsafe { Box::from_raw(ptr) };
WriterBox { inner, vtable }
}
pub fn set_seek(&mut self)
where
W: Seek,
{
self.vtable.seek = Some(lifetime_erase_trait_vtable!((&mut self.inner): '_ as Seek));
}
pub fn set_any(&mut self)
where
W: Any,
{
self.vtable.any = Some(lifetime_erase_trait_vtable!((&mut self.inner): '_ as Any));
}
}
impl<W> Writer<W> {
pub fn as_write(&self) -> &(dyn Write + '_) {
let ptr = &self.inner as *const W;
let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.write);
unsafe { &*local }
}
pub fn as_write_mut(&mut self) -> &mut (dyn Write + '_) {
let ptr = &mut self.inner as *mut W;
let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.write);
unsafe { &mut *local }
}
pub fn as_seek(&self) -> Option<&(dyn Seek + '_)> {
let ptr = &self.inner as *const W;
let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.vtable.seek?);
Some(unsafe { &*local })
}
pub fn as_seek_mut(&mut self) -> Option<&mut (dyn Seek + '_)> {
let ptr = &mut self.inner as *mut W;
let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.vtable.seek?);
Some(unsafe { &mut *local })
}
pub fn as_any(&self) -> Option<&'_ dyn Any> {
let ptr = &self.inner as *const W;
let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.vtable.any?);
Some(unsafe { &*local })
}
pub fn as_any_mut(&mut self) -> Option<&'_ mut dyn Any> {
let ptr = &mut self.inner as *mut W;
let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.vtable.any?);
Some(unsafe { &mut *local })
}
pub fn into_inner(self) -> W {
self.inner
}
}
impl WriterMut<'_> {
pub fn as_write_mut(&mut self) -> &mut (dyn Write + '_) {
&mut *self.inner
}
pub fn as_seek_mut(&mut self) -> Option<&mut (dyn Seek + '_)> {
let ptr = self.inner as *mut dyn Write;
let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.vtable.seek?);
Some(unsafe { &mut *local })
}
pub fn as_any(&self) -> Option<&'_ dyn Any> {
let ptr = self.inner as *const dyn Write;
let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.vtable.any?);
Some(unsafe { &*local })
}
pub fn as_any_mut(&mut self) -> Option<&'_ mut dyn Any> {
let ptr = self.inner as *mut dyn Write;
let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.vtable.any?);
Some(unsafe { &mut *local })
}
}
impl WriterBox<'_> {
pub fn as_mut(&mut self) -> WriterMut<'_> {
WriterMut {
vtable: self.vtable,
inner: self.as_read_mut(),
}
}
pub fn as_read_mut(&mut self) -> &mut (dyn Write + '_) {
&mut *self.inner
}
pub fn as_seek_mut(&mut self) -> Option<&mut (dyn Seek + '_)> {
let ptr = self.inner.as_mut() as *mut _;
let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.vtable.seek?);
Some(unsafe { &mut *local })
}
pub fn as_any(&self) -> Option<&'_ dyn Any> {
let ptr = self.inner.as_ref() as *const _;
let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.vtable.any?);
Some(unsafe { &*local })
}
pub fn as_any_mut(&mut self) -> Option<&'_ mut dyn Any> {
let ptr = self.inner.as_mut() as *mut _;
let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.vtable.any?);
Some(unsafe { &mut *local })
}
}
impl<'lt, R> From<&'lt mut Writer<R>> for WriterMut<'lt> {
fn from(value: &'lt mut Writer<R>) -> Self {
value.as_mut()
}
}
impl<'lt, R: 'lt> From<Writer<R>> for WriterBox<'lt> {
fn from(value: Writer<R>) -> Self {
value.into_boxed()
}
}
impl<'lt> From<&'lt mut WriterBox<'_>> for WriterMut<'lt> {
fn from(value: &'lt mut WriterBox) -> Self {
value.as_mut()
}
}