thindx/headers/d3dcommon.h/interfaces/
blob.rs1use crate::*;
2
3use winapi::um::d3dcommon::ID3DBlob;
4
5use std::borrow::{Borrow, Cow};
6use std::fmt::{self, Debug, Display, Formatter};
7use std::ops::{Deref, Index};
8use std::slice::SliceIndex;
9use std::str::Utf8Error;
10
11
12
13#[derive(Clone)]
23#[repr(transparent)]
24pub struct ReadOnlyBlob(pub(crate) mcom::Rc<ID3DBlob>);
25
26convert!(unsafe ReadOnlyBlob => Unknown, winapi::um::d3dcommon::ID3DBlob);
27
28impl ReadOnlyBlob {
29 pub fn get_buffer_size(&self) -> usize {
34 unsafe { self.0.GetBufferSize() }
35 }
36
37 pub fn get_buffer(&self) -> &[u8] {
42 let size = self.get_buffer_size();
43 let ptr = unsafe { self.0.GetBufferPointer() } as *const u8;
44 unsafe { std::slice::from_raw_parts(ptr, size) }
45 }
46
47 pub fn as_bytes(&self) -> &[u8] {
49 self.get_buffer()
50 }
51
52
53 pub fn bytes(&self) -> impl Iterator<Item = u8> + '_ {
55 self.get_buffer().iter().copied()
56 }
57}
58
59impl AsRef <[u8]> for ReadOnlyBlob { fn as_ref(&self) -> &[u8] { self.get_buffer() } }
60impl Borrow<[u8]> for ReadOnlyBlob { fn borrow(&self) -> &[u8] { self.get_buffer() } }
61impl Debug for ReadOnlyBlob { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { write!(fmt, "ReadOnlyBlob({} bytes)", self.get_buffer_size()) } }
62impl<I> Index<I> for ReadOnlyBlob where I: SliceIndex<[u8]> { fn index(&self, index: I) -> &Self::Output { self.get_buffer().index(index) } type Output = I::Output; }
63
64#[test] fn layout() {
74 use std::mem::*;
75 assert_eq!(align_of::<Option<ReadOnlyBlob>>(), align_of::<*mut ID3DBlob>());
76 assert_eq!(size_of::< Option<ReadOnlyBlob>>(), size_of::< *mut ID3DBlob>());
77}
78
79
80
81#[derive(Clone, Default)]
83pub struct TextBlob(Option<ReadOnlyBlob>);
84
85impl TextBlob {
86 pub fn new(value: impl Into<Self>) -> Self { value.into() }
89
90 pub fn is_empty(&self) -> bool { self.0.as_ref().map_or(true, |blob| {
92 let b = blob.get_buffer();
93 b.is_empty() || b == [0]
94 })}
95
96 pub fn to_utf8_lossy(&self) -> Cow<str> { String::from_utf8_lossy(self.as_bytes()) }
98
99 pub fn to_utf8(&self) -> Result<&str, Utf8Error> { std::str::from_utf8(self.as_bytes()) }
101
102 }
104
105impl Debug for TextBlob { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { write!(fmt, "TextBlob({:?})", self.to_utf8_lossy()) } }
106impl Display for TextBlob { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { Display::fmt(&self.to_utf8_lossy(), fmt) } }
107
108impl From<Option<ReadOnlyBlob>> for TextBlob { fn from(value: Option<ReadOnlyBlob>) -> Self { Self( value ) } }
109impl From< ReadOnlyBlob > for TextBlob { fn from(value: ReadOnlyBlob ) -> Self { Self(Some(value)) } }
110
111impl TextBlob {
112 fn as_bytes(&self) -> &[u8] {
113 self.0.as_ref().map_or(&[], |blob| {
114 let b = blob.get_buffer();
115 if b.last() == Some(&0) {
116 &b[..b.len()-1]
117 } else {
118 b
119 }
120 })
121 }
122}
123
124
125
126#[derive(Clone)]
128#[repr(transparent)]
129pub struct CodeBlob(ReadOnlyBlob);
130
131impl CodeBlob {
132 pub(crate) unsafe fn from_unchecked(value: ReadOnlyBlob) -> Self { Self(value) }
143
144 #[allow(clippy::len_without_is_empty)] pub fn len(&self) -> usize { self.0.get_buffer_size() }
147
148 pub fn as_bytes(&self) -> &[u8] { self.0.get_buffer() }
150
151 pub fn as_bytecode(&self) -> &d3d::Bytecode { unsafe { d3d::Bytecode::from_unchecked(self.as_bytes()) } }
153}
154
155impl AsRef <[u8]> for CodeBlob { fn as_ref(&self) -> &[u8] { self.as_bytes() } }
156impl Borrow<[u8]> for CodeBlob { fn borrow(&self) -> &[u8] { self.as_bytes() } }
157impl AsRef <d3d::Bytecode> for CodeBlob { fn as_ref(&self) -> &d3d::Bytecode { self.as_bytecode() } }
158impl Borrow<d3d::Bytecode> for CodeBlob { fn borrow(&self) -> &d3d::Bytecode { self.as_bytecode() } }
159impl Debug for CodeBlob { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { write!(fmt, "CodeBlob({} bytes)", self.len()) } }
160impl Deref for CodeBlob { fn deref(&self) -> &d3d::Bytecode { self.as_bytecode() } type Target = d3d::Bytecode; }
161
162#[derive(Clone)]
172#[repr(transparent)]
173pub struct BytesBlob(Option<ReadOnlyBlob>);
174
175impl BytesBlob {
176 pub fn new(value: impl Into<Self>) -> Self { value.into() }
179
180 pub fn len(&self) -> usize { self.0.as_ref().map_or(0, |blob| blob.get_buffer_size()) }
182
183 pub fn is_empty(&self) -> bool { self.0.as_ref().map_or(true, |blob| blob.get_buffer_size() == 0) }
185
186 pub fn as_bytes(&self) -> &[u8] { self.0.as_ref().map_or(&[], |blob| blob.get_buffer()) }
188}
189
190impl AsRef <[u8]> for BytesBlob { fn as_ref(&self) -> &[u8] { self.as_bytes() } }
191impl Borrow<[u8]> for BytesBlob { fn borrow(&self) -> &[u8] { self.as_bytes() } }
192impl Debug for BytesBlob { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { write!(fmt, "BytesBlob({} bytes)", self.len()) } }
193impl Deref for BytesBlob { fn deref(&self) -> &[u8] { self.as_bytes() } type Target = [u8]; }
194impl From<Option<ReadOnlyBlob>> for BytesBlob { fn from(value: Option<ReadOnlyBlob>) -> Self { Self( value ) } }
195impl From< ReadOnlyBlob > for BytesBlob { fn from(value: ReadOnlyBlob ) -> Self { Self(Some(value)) } }