gio/
io_extension_point.rs1use std::{marker::PhantomData, ptr};
4
5use glib::{translate::*, GString, Type};
6
7use crate::{ffi, IOExtension};
8
9#[derive(Debug)]
12#[must_use = "The builder must be built to be used"]
13pub struct IOExtensionPointBuilder {
14 name: GString,
15 required_type: Option<Type>,
16}
17
18impl IOExtensionPointBuilder {
19 fn new(name: GString) -> Self {
20 Self {
21 name,
22 required_type: None,
23 }
24 }
25
26 #[doc(alias = "g_io_extension_point_set_required_type")]
27 pub fn required_type(self, required_type: Type) -> Self {
28 Self {
29 required_type: Some(required_type),
30 ..self
31 }
32 }
33
34 #[must_use = "Building the object from the builder is usually expensive and is not expected to have side effects"]
35 pub fn build(self) -> IOExtensionPoint {
36 unsafe {
37 let ep = IOExtensionPoint::from_glib_none(ffi::g_io_extension_point_register(
38 self.name.to_glib_none().0,
39 ));
40 if let Some(t) = self.required_type {
41 ffi::g_io_extension_point_set_required_type(ep.0.as_ptr(), t.into_glib());
42 }
43 ep
44 }
45 }
46}
47
48#[doc(alias = "GIOExtensionPoint")]
53#[derive(Debug, Copy, Clone, Eq, PartialEq)]
54pub struct IOExtensionPoint(ptr::NonNull<ffi::GIOExtensionPoint>);
55
56impl FromGlibPtrNone<*mut ffi::GIOExtensionPoint> for IOExtensionPoint {
57 #[inline]
58 unsafe fn from_glib_none(ptr: *mut ffi::GIOExtensionPoint) -> Self {
59 debug_assert!(!ptr.is_null());
60 IOExtensionPoint(ptr::NonNull::new_unchecked(ptr))
61 }
62}
63
64impl<'a> ToGlibPtr<'a, *mut ffi::GIOExtensionPoint> for &'a IOExtensionPoint {
65 type Storage = PhantomData<&'a IOExtensionPoint>;
66
67 #[inline]
68 fn to_glib_none(&self) -> Stash<'a, *mut ffi::GIOExtensionPoint, &'a IOExtensionPoint> {
69 Stash(self.0.as_ptr() as *mut ffi::GIOExtensionPoint, PhantomData)
70 }
71}
72
73impl IOExtensionPoint {
74 #[doc(alias = "g_io_extension_point_register")]
77 pub fn builder(name: impl Into<GString>) -> IOExtensionPointBuilder {
78 IOExtensionPointBuilder::new(name.into())
79 }
80
81 #[doc(alias = "g_io_extension_point_lookup")]
82 pub fn lookup(name: impl IntoGStr) -> Option<Self> {
83 name.run_with_gstr(|name| unsafe {
84 let ep = ffi::g_io_extension_point_lookup(name.to_glib_none().0);
85 from_glib_none(ep)
86 })
87 }
88
89 #[doc(alias = "g_io_extension_point_get_extensions")]
90 pub fn extensions(&self) -> Vec<IOExtension> {
91 let mut res = Vec::new();
92 unsafe {
93 let mut l = ffi::g_io_extension_point_get_extensions(self.0.as_ptr());
94 while !l.is_null() {
95 let e: *mut ffi::GIOExtension = Ptr::from((*l).data);
96 res.push(from_glib_none(e));
97 l = (*l).next;
98 }
99 }
100 res
101 }
102
103 #[doc(alias = "g_io_extension_point_get_extension_by_name")]
104 pub fn extension_by_name(&self, name: impl IntoGStr) -> Option<IOExtension> {
105 name.run_with_gstr(|name| unsafe {
106 let e = ffi::g_io_extension_point_get_extension_by_name(
107 self.0.as_ptr(),
108 name.to_glib_none().0,
109 );
110 from_glib_none(e)
111 })
112 }
113
114 #[doc(alias = "g_io_extension_point_get_required_type")]
115 pub fn required_type(&self) -> Type {
116 unsafe { from_glib(ffi::g_io_extension_point_get_required_type(self.0.as_ptr())) }
117 }
118
119 #[doc(alias = "g_io_extension_point_implement")]
120 pub fn implement(
121 extension_point_name: impl IntoGStr,
122 type_: Type,
123 extension_name: impl IntoGStr,
124 priority: i32,
125 ) -> Option<IOExtension> {
126 extension_point_name.run_with_gstr(|extension_point_name| {
127 extension_name.run_with_gstr(|extension_name| unsafe {
128 let e = ffi::g_io_extension_point_implement(
129 extension_point_name.to_glib_none().0,
130 type_.into_glib(),
131 extension_name.to_glib_none().0,
132 priority,
133 );
134 from_glib_none(e)
135 })
136 })
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use glib::prelude::*;
143
144 use super::*;
145
146 #[test]
147 fn extension_point() {
148 let ep = IOExtensionPoint::lookup("test-extension-point");
149 assert!(ep.is_none());
150
151 let ep = IOExtensionPoint::builder("test-extension-point").build();
152 let ep2 = IOExtensionPoint::lookup("test-extension-point");
153 assert_eq!(ep2, Some(ep));
154
155 let req = ep.required_type();
156 assert_eq!(req, Type::INVALID);
157
158 let ep = IOExtensionPoint::builder("test-extension-point")
159 .required_type(Type::OBJECT)
160 .build();
161 let req = ep.required_type();
162 assert_eq!(req, Type::OBJECT);
163
164 let v = ep.extensions();
165 assert!(v.is_empty());
166
167 let e = IOExtensionPoint::implement(
168 "test-extension-point",
169 <crate::Vfs as StaticType>::static_type(),
170 "extension1",
171 10,
172 );
173 assert!(e.is_some());
174
175 let e = IOExtensionPoint::implement("test-extension-point", Type::OBJECT, "extension2", 20);
176 assert!(e.is_some());
177
178 let v = ep.extensions();
179 assert_eq!(v.len(), 2);
180 assert_eq!(v[0].name(), "extension2");
181 assert_eq!(v[0].type_(), Type::OBJECT);
182 assert_eq!(v[0].priority(), 20);
183 assert_eq!(v[1].name(), "extension1");
184 assert_eq!(v[1].type_(), <crate::Vfs as StaticType>::static_type());
185 assert_eq!(v[1].priority(), 10);
186 }
187}