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