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