gstreamer/subclass/
allocator.rs
1use std::ptr;
4
5use glib::{bool_error, prelude::*, subclass::prelude::*, translate::*, BoolError};
6
7use super::prelude::*;
8use crate::{ffi, AllocationParams, Allocator, Memory};
9
10pub trait AllocatorImpl: GstObjectImpl + ObjectSubclass<Type: IsA<Allocator>> {
11 fn alloc(&self, size: usize, params: Option<&AllocationParams>) -> Result<Memory, BoolError> {
35 self.parent_alloc(size, params)
36 }
37
38 fn free(&self, memory: Memory) {
39 self.parent_free(memory)
40 }
41}
42
43pub trait AllocatorImplExt: AllocatorImpl {
44 fn parent_alloc(
45 &self,
46 size: usize,
47 params: Option<&AllocationParams>,
48 ) -> Result<Memory, BoolError> {
49 unsafe {
50 let data = Self::type_data();
51 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAllocatorClass;
52
53 if let Some(f) = (*parent_class).alloc {
54 from_glib_full::<*mut ffi::GstMemory, Option<_>>(f(
55 self.obj().unsafe_cast_ref::<Allocator>().to_glib_none().0,
56 size,
57 mut_override(params.to_glib_none().0),
58 ))
59 .ok_or_else(|| bool_error!("Allocation failed"))
60 } else {
61 Err(bool_error!("No allocation method on parent class"))
62 }
63 }
64 }
65
66 fn parent_free(&self, memory: Memory) {
67 unsafe {
68 let data = Self::type_data();
69 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAllocatorClass;
70
71 if let Some(f) = (*parent_class).free {
72 f(
73 self.obj().unsafe_cast_ref::<Allocator>().to_glib_none().0,
74 memory.into_glib_ptr(),
75 )
76 }
77 }
78 }
79}
80
81impl<T: AllocatorImpl> AllocatorImplExt for T {}
82
83unsafe impl<T: AllocatorImpl> IsSubclassable<T> for Allocator {
84 fn class_init(klass: &mut glib::Class<Self>) {
85 Self::parent_class_init::<T>(klass);
86 let klass = klass.as_mut();
87 klass.alloc = Some(alloc::<T>);
88 klass.free = Some(free::<T>);
89 }
90}
91
92unsafe extern "C" fn alloc<T: AllocatorImpl>(
93 ptr: *mut ffi::GstAllocator,
94 size: usize,
95 params: *mut ffi::GstAllocationParams,
96) -> *mut ffi::GstMemory {
97 let instance = &*(ptr as *mut T::Instance);
98 let imp = instance.imp();
99 let instance = imp.obj();
100
101 let params = if params.is_null() {
102 None
103 } else {
104 Some(&*(params as *mut AllocationParams))
105 };
106
107 imp.alloc(size, params)
108 .map(|memory| memory.into_glib_ptr())
109 .unwrap_or_else(|error| {
110 error!(crate::CAT_RUST, obj = instance, "{:?}", error);
111
112 ptr::null_mut()
113 })
114}
115
116unsafe extern "C" fn free<T: AllocatorImpl>(
117 ptr: *mut ffi::GstAllocator,
118 memory: *mut ffi::GstMemory,
119) {
120 let instance = &*(ptr as *mut T::Instance);
121 let imp = instance.imp();
122 let memory = from_glib_full(memory);
123
124 imp.free(memory);
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130 use crate::prelude::*;
131
132 pub mod imp {
133 use super::*;
134
135 #[derive(Default)]
136 pub struct TestAllocator;
137
138 impl ObjectImpl for TestAllocator {}
139 impl GstObjectImpl for TestAllocator {}
140 impl AllocatorImpl for TestAllocator {
141 fn alloc(
142 &self,
143 size: usize,
144 _params: Option<&AllocationParams>,
145 ) -> Result<Memory, BoolError> {
146 Ok(Memory::from_slice(vec![0; size]))
147 }
148
149 fn free(&self, memory: Memory) {
150 self.parent_free(memory)
151 }
152 }
153
154 #[glib::object_subclass]
155 impl ObjectSubclass for TestAllocator {
156 const NAME: &'static str = "TestAllocator";
157 type Type = super::TestAllocator;
158 type ParentType = Allocator;
159 }
160 }
161
162 glib::wrapper! {
163 pub struct TestAllocator(ObjectSubclass<imp::TestAllocator>) @extends Allocator, crate::Object;
164 }
165
166 impl Default for TestAllocator {
167 fn default() -> Self {
168 glib::Object::new()
169 }
170 }
171
172 #[test]
173 fn test_allocator_registration() {
174 crate::init().unwrap();
175
176 const TEST_ALLOCATOR_NAME: &str = "TestAllocator";
177
178 let allocator = TestAllocator::default();
179 Allocator::register(TEST_ALLOCATOR_NAME, allocator);
180
181 let allocator = Allocator::find(Some(TEST_ALLOCATOR_NAME));
182
183 assert!(allocator.is_some());
184 }
185
186 #[test]
187 fn test_allocator_alloc() {
188 crate::init().unwrap();
189
190 const SIZE: usize = 1024;
191
192 let allocator = TestAllocator::default();
193
194 let memory = allocator.alloc(SIZE, None).unwrap();
195
196 assert_eq!(memory.size(), SIZE);
197 }
198}