1use std::marker::PhantomData;
4
5use glib::{object::IsClass, prelude::*, Object, Type};
6
7use crate::{prelude::*, Cancellable, Initable};
8
9impl Initable {
10 #[track_caller]
16 #[allow(clippy::new_ret_no_self)]
17 pub fn new<T: IsA<Object> + IsClass + IsA<Initable>>(
18 cancellable: Option<&impl IsA<Cancellable>>,
19 ) -> Result<T, glib::Error> {
20 let object = Self::with_type(T::static_type(), cancellable)?;
21 Ok(unsafe { object.unsafe_cast() })
22 }
23
24 #[track_caller]
30 pub fn with_type(
31 type_: Type,
32 cancellable: Option<&impl IsA<Cancellable>>,
33 ) -> Result<Object, glib::Error> {
34 if !type_.is_a(Initable::static_type()) {
35 panic!("Type '{type_}' is not initable");
36 }
37
38 unsafe {
39 let object = Object::new_internal(type_, &mut []);
40 object.unsafe_cast_ref::<Self>().init(cancellable)?;
41 Ok(object)
42 }
43 }
44
45 #[track_caller]
54 pub fn with_mut_values(
55 type_: Type,
56 properties: &mut [(&str, glib::Value)],
57 cancellable: Option<&impl IsA<Cancellable>>,
58 ) -> Result<Object, glib::Error> {
59 if !type_.is_a(Initable::static_type()) {
60 panic!("Type '{type_}' is not initable");
61 }
62
63 unsafe {
64 let object = Object::new_internal(type_, properties);
65 object.unsafe_cast_ref::<Self>().init(cancellable)?;
66 Ok(object)
67 }
68 }
69
70 pub fn builder<'a, O: IsA<Object> + IsClass + IsA<Initable>>() -> InitableBuilder<'a, O> {
73 InitableBuilder::new(O::static_type())
74 }
75
76 pub fn builder_with_type<'a>(type_: Type) -> InitableBuilder<'a, Object> {
79 if !type_.is_a(Initable::static_type()) {
80 panic!("Type '{type_}' is not initable");
81 }
82
83 InitableBuilder::new(type_)
84 }
85}
86
87#[must_use = "builder doesn't do anything unless built"]
88pub struct InitableBuilder<'a, O> {
89 type_: Type,
90 properties: smallvec::SmallVec<[(&'a str, glib::Value); 16]>,
91 phantom: PhantomData<O>,
92}
93
94impl<'a, O: IsA<Object> + IsClass> InitableBuilder<'a, O> {
95 #[inline]
96 fn new(type_: Type) -> Self {
97 InitableBuilder {
98 type_,
99 properties: smallvec::SmallVec::new(),
100 phantom: PhantomData,
101 }
102 }
103
104 #[inline]
107 pub fn type_(&self) -> Type {
108 self.type_
109 }
110
111 #[inline]
114 pub fn property(self, name: &'a str, value: impl Into<glib::Value>) -> Self {
115 let InitableBuilder {
116 type_,
117 mut properties,
118 ..
119 } = self;
120 properties.push((name, value.into()));
121
122 InitableBuilder {
123 type_,
124 properties,
125 phantom: PhantomData,
126 }
127 }
128
129 #[track_caller]
137 #[inline]
138 pub fn build(mut self, cancellable: Option<&impl IsA<Cancellable>>) -> Result<O, glib::Error> {
139 let object = Initable::with_mut_values(self.type_, &mut self.properties, cancellable)?;
140 Ok(unsafe { object.unsafe_cast::<O>() })
141 }
142}