gio/initable.rs
1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::marker::PhantomData;
4
5use glib::{Object, Type, object::IsClass, prelude::*};
6
7use crate::{Cancellable, Initable, prelude::*};
8
9impl Initable {
10 // rustdoc-stripper-ignore-next
11 /// Create a new instance of an object with the default property values.
12 ///
13 /// Similar to [`Object::new`] but can fail because the object initialization in
14 /// `Initable::init` failed.
15 // rustdoc-stripper-ignore-next-stop
16 /// Helper function for constructing #GInitable object. This is
17 /// similar to g_object_new() but also initializes the object
18 /// and returns [`None`], setting an error on failure.
19 /// ## `object_type`
20 /// a #GType supporting #GInitable.
21 /// ## `cancellable`
22 /// optional #GCancellable object, [`None`] to ignore.
23 /// ## `error`
24 /// a #GError location to store the error occurring, or [`None`] to
25 /// ignore.
26 /// ## `first_property_name`
27 /// the name of the first property, or [`None`] if no
28 /// properties
29 ///
30 /// # Returns
31 ///
32 /// a newly allocated
33 /// #GObject, or [`None`] on error
34 #[track_caller]
35 #[allow(clippy::new_ret_no_self)]
36 pub fn new<T: IsA<Object> + IsClass + IsA<Initable>>(
37 cancellable: Option<&impl IsA<Cancellable>>,
38 ) -> Result<T, glib::Error> {
39 let object = Self::with_type(T::static_type(), cancellable)?;
40 Ok(unsafe { object.unsafe_cast() })
41 }
42
43 // rustdoc-stripper-ignore-next
44 /// Create a new instance of an object with the default property values.
45 ///
46 /// Similar to [`Object::with_type`] but can fail because the object initialization in
47 /// `Initable::init` failed.
48 #[track_caller]
49 pub fn with_type(
50 type_: Type,
51 cancellable: Option<&impl IsA<Cancellable>>,
52 ) -> Result<Object, glib::Error> {
53 if !type_.is_a(Initable::static_type()) {
54 panic!("Type '{type_}' is not initable");
55 }
56
57 unsafe {
58 let object = Object::new_internal(type_, &mut []);
59 object.unsafe_cast_ref::<Self>().init(cancellable)?;
60 Ok(object)
61 }
62 }
63
64 // rustdoc-stripper-ignore-next
65 /// Create a new instance of an object of the given type with the given properties as mutable
66 /// values.
67 ///
68 /// # Panics
69 ///
70 /// This panics if the object is not instantiable, doesn't have all the given properties or
71 /// property values of the wrong type are provided.
72 #[track_caller]
73 pub fn with_mut_values(
74 type_: Type,
75 properties: &mut [(&str, glib::Value)],
76 cancellable: Option<&impl IsA<Cancellable>>,
77 ) -> Result<Object, glib::Error> {
78 if !type_.is_a(Initable::static_type()) {
79 panic!("Type '{type_}' is not initable");
80 }
81
82 unsafe {
83 let object = Object::new_internal(type_, properties);
84 object.unsafe_cast_ref::<Self>().init(cancellable)?;
85 Ok(object)
86 }
87 }
88
89 // rustdoc-stripper-ignore-next
90 /// Create a new object builder for a specific type.
91 pub fn builder<'a, O: IsA<Object> + IsClass + IsA<Initable>>() -> InitableBuilder<'a, O> {
92 InitableBuilder::new(O::static_type())
93 }
94
95 // rustdoc-stripper-ignore-next
96 /// Create a new object builder for a specific type.
97 pub fn builder_with_type<'a>(type_: Type) -> InitableBuilder<'a, Object> {
98 if !type_.is_a(Initable::static_type()) {
99 panic!("Type '{type_}' is not initable");
100 }
101
102 InitableBuilder::new(type_)
103 }
104}
105
106#[must_use = "builder doesn't do anything unless built"]
107pub struct InitableBuilder<'a, O> {
108 type_: Type,
109 properties: smallvec::SmallVec<[(&'a str, glib::Value); 16]>,
110 phantom: PhantomData<O>,
111}
112
113impl<'a, O: IsA<Object> + IsClass> InitableBuilder<'a, O> {
114 #[inline]
115 fn new(type_: Type) -> Self {
116 InitableBuilder {
117 type_,
118 properties: smallvec::SmallVec::new(),
119 phantom: PhantomData,
120 }
121 }
122
123 // rustdoc-stripper-ignore-next
124 /// Gets the type of this builder.
125 #[inline]
126 pub fn type_(&self) -> Type {
127 self.type_
128 }
129
130 // rustdoc-stripper-ignore-next
131 /// Set property `name` to the given value `value`.
132 #[inline]
133 pub fn property(self, name: &'a str, value: impl Into<glib::Value>) -> Self {
134 let InitableBuilder {
135 type_,
136 mut properties,
137 ..
138 } = self;
139 properties.push((name, value.into()));
140
141 InitableBuilder {
142 type_,
143 properties,
144 phantom: PhantomData,
145 }
146 }
147
148 // rustdoc-stripper-ignore-next
149 /// Build the object with the provided properties.
150 ///
151 /// # Panics
152 ///
153 /// This panics if the object is not instantiable, doesn't have all the given properties or
154 /// property values of the wrong type are provided.
155 #[track_caller]
156 #[inline]
157 pub fn build(mut self, cancellable: Option<&impl IsA<Cancellable>>) -> Result<O, glib::Error> {
158 let object = Initable::with_mut_values(self.type_, &mut self.properties, cancellable)?;
159 Ok(unsafe { object.unsafe_cast::<O>() })
160 }
161}