pdf/
any.rs

1use std::any::TypeId;
2use std::rc::Rc;
3use std::sync::Arc;
4use datasize::DataSize;
5use crate::object::{Object};
6use crate::error::{Result, PdfError};
7
8pub trait AnyObject {
9    fn type_name(&self) -> &'static str;
10    fn type_id(&self) -> TypeId;
11    fn size(&self) -> usize;
12}
13
14#[repr(transparent)]
15pub struct NoSize<T>(T);
16impl<T: 'static> AnyObject for NoSize<T> {
17    fn size(&self) -> usize {
18        0
19    }
20    fn type_id(&self) -> TypeId {
21        TypeId::of::<T>()
22    }
23    fn type_name(&self) -> &'static str {
24        std::any::type_name::<T>()
25    }
26}
27
28#[repr(transparent)]
29pub struct WithSize<T>(T);
30impl<T: DataSize + 'static> AnyObject for WithSize<T> {
31    fn size(&self) -> usize {
32        datasize::data_size(&self.0)
33    }
34    fn type_id(&self) -> TypeId {
35        TypeId::of::<T>()
36    }
37    fn type_name(&self) -> &'static str {
38        std::any::type_name::<T>()
39    }
40}
41
42#[derive(DataSize)]
43pub struct Any(Rc<dyn AnyObject>);
44
45impl Any {
46    pub fn downcast<T>(self) -> Result<Rc<T>> 
47        where T: AnyObject + 'static
48    {
49        if TypeId::of::<T>() == self.0.type_id() {
50            unsafe {
51                let raw: *const dyn AnyObject = Rc::into_raw(self.0);
52                Ok(Rc::from_raw(raw as *const T))
53            }
54        } else {
55            Err(type_mismatch::<T>(self.0.type_name()))
56        }
57    }
58    pub fn new<T>(rc: Rc<T>) -> Any
59        where WithSize<T>: AnyObject, T: 'static
60    {
61        Any(unsafe {
62            std::mem::transmute::<Rc<T>, Rc<WithSize<T>>>(rc)
63        } as _)
64    }
65    pub fn new_without_size<T>(rc: Rc<T>) -> Any
66        where NoSize<T>: AnyObject, T: 'static
67    {
68        Any(unsafe {
69            std::mem::transmute::<Rc<T>, Rc<NoSize<T>>>(rc)
70        } as _)
71    }
72    pub fn type_name(&self) -> &'static str {
73        self.0.type_name()
74    }
75}
76
77#[derive(Clone, DataSize)]
78pub struct AnySync(Arc<dyn AnyObject+Sync+Send>);
79
80#[cfg(feature="cache")]
81impl globalcache::ValueSize for AnySync {
82    #[inline]
83    fn size(&self) -> usize {
84        self.0.size()
85    }
86}
87
88impl AnySync {
89    pub fn downcast<T>(self) -> Result<Arc<T>> 
90        where T: 'static
91    {
92        if TypeId::of::<T>() == self.0.type_id() {
93            unsafe {
94                let raw: *const (dyn AnyObject+Sync+Send) = Arc::into_raw(self.0);
95                Ok(Arc::from_raw(raw as *const T))
96            }
97        } else {
98            Err(type_mismatch::<T>(self.0.type_name()))
99        }
100    }
101    pub fn new<T>(arc: Arc<T>) -> AnySync
102        where WithSize<T>: AnyObject, T: Sync + Send + 'static
103    {
104        AnySync(unsafe {
105            std::mem::transmute::<Arc<T>, Arc<WithSize<T>>>(arc)
106        } as _)
107    }
108    pub fn new_without_size<T>(arc: Arc<T>) -> AnySync
109        where NoSize<T>: AnyObject, T: Sync + Send + 'static
110    {
111        AnySync(unsafe {
112            std::mem::transmute::<Arc<T>, Arc<NoSize<T>>>(arc)
113        } as _)
114    }
115    pub fn type_name(&self) -> &'static str {
116        self.0.type_name()
117    }
118}
119fn type_mismatch<T>(name: &str) -> PdfError {
120    PdfError::Other { msg: format!("expected {}, found {}", std::any::type_name::<T>(), name) }
121}