1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use std::{cmp, ffi::CStr, fmt, ops::Deref, ptr}; |
4 | |
5 | use crate::{ |
6 | ffi, gobject_ffi, prelude::*, translate::*, ParamSpecEnum, ParamSpecFlags, Type, TypeInfo, |
7 | Value, |
8 | }; |
9 | |
10 | #[derive (Clone, Copy, Debug, Eq, PartialEq, Hash)] |
11 | pub enum UserDirectory { |
12 | #[doc (alias = "G_USER_DIRECTORY_DESKTOP" )] |
13 | Desktop, |
14 | #[doc (alias = "G_USER_DIRECTORY_DOCUMENTS" )] |
15 | Documents, |
16 | #[doc (alias = "G_USER_DIRECTORY_DOWNLOAD" )] |
17 | Downloads, |
18 | #[doc (alias = "G_USER_DIRECTORY_MUSIC" )] |
19 | Music, |
20 | #[doc (alias = "G_USER_DIRECTORY_PICTURES" )] |
21 | Pictures, |
22 | #[doc (alias = "G_USER_DIRECTORY_PUBLIC_SHARE" )] |
23 | PublicShare, |
24 | #[doc (alias = "G_USER_DIRECTORY_TEMPLATES" )] |
25 | Templates, |
26 | #[doc (alias = "G_USER_DIRECTORY_VIDEOS" )] |
27 | Videos, |
28 | } |
29 | |
30 | #[doc (hidden)] |
31 | impl IntoGlib for UserDirectory { |
32 | type GlibType = ffi::GUserDirectory; |
33 | |
34 | #[inline ] |
35 | fn into_glib(self) -> ffi::GUserDirectory { |
36 | match self { |
37 | Self::Desktop => ffi::G_USER_DIRECTORY_DESKTOP, |
38 | Self::Documents => ffi::G_USER_DIRECTORY_DOCUMENTS, |
39 | Self::Downloads => ffi::G_USER_DIRECTORY_DOWNLOAD, |
40 | Self::Music => ffi::G_USER_DIRECTORY_MUSIC, |
41 | Self::Pictures => ffi::G_USER_DIRECTORY_PICTURES, |
42 | Self::PublicShare => ffi::G_USER_DIRECTORY_PUBLIC_SHARE, |
43 | Self::Templates => ffi::G_USER_DIRECTORY_TEMPLATES, |
44 | Self::Videos => ffi::G_USER_DIRECTORY_VIDEOS, |
45 | } |
46 | } |
47 | } |
48 | |
49 | // rustdoc-stripper-ignore-next |
50 | /// Representation of an `enum` for dynamically, at runtime, querying the values of the enum and |
51 | /// using them. |
52 | #[doc (alias = "GEnumClass" )] |
53 | #[repr (transparent)] |
54 | pub struct EnumClass(ptr::NonNull<gobject_ffi::GEnumClass>); |
55 | |
56 | unsafe impl Send for EnumClass {} |
57 | unsafe impl Sync for EnumClass {} |
58 | |
59 | impl fmt::Debug for EnumClass { |
60 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
61 | f&mut DebugStruct<'_, '_>.debug_struct("EnumClass" ) |
62 | .field("type" , &self.type_()) |
63 | .field(name:"values" , &self.values()) |
64 | .finish() |
65 | } |
66 | } |
67 | |
68 | impl EnumClass { |
69 | // rustdoc-stripper-ignore-next |
70 | /// Create a new `EnumClass` from a static type `T`. |
71 | /// |
72 | /// Panics if `T` is not representing an enum. |
73 | pub fn new<T: StaticType + HasParamSpec<ParamSpec = ParamSpecEnum>>() -> Self { |
74 | Self::with_type(T::static_type()).expect("invalid enum class" ) |
75 | } |
76 | // rustdoc-stripper-ignore-next |
77 | /// Create a new `EnumClass` from a `Type`. |
78 | /// |
79 | /// Returns `None` if `type_` is not representing an enum. |
80 | pub fn with_type(type_: Type) -> Option<Self> { |
81 | unsafe { |
82 | let is_enum: bool = from_glib(gobject_ffi::g_type_is_a( |
83 | type_.into_glib(), |
84 | gobject_ffi::G_TYPE_ENUM, |
85 | )); |
86 | if !is_enum { |
87 | return None; |
88 | } |
89 | |
90 | Some(EnumClass( |
91 | ptr::NonNull::new(gobject_ffi::g_type_class_ref(type_.into_glib()) as *mut _) |
92 | .unwrap(), |
93 | )) |
94 | } |
95 | } |
96 | |
97 | // rustdoc-stripper-ignore-next |
98 | /// `Type` of the enum. |
99 | pub fn type_(&self) -> Type { |
100 | unsafe { from_glib(self.0.as_ref().g_type_class.g_type) } |
101 | } |
102 | |
103 | // rustdoc-stripper-ignore-next |
104 | /// Gets `EnumValue` by integer `value`, if existing. |
105 | /// |
106 | /// Returns `None` if the enum does not contain any value |
107 | /// with `value`. |
108 | #[doc (alias = "g_enum_get_value" )] |
109 | #[doc (alias = "get_value" )] |
110 | pub fn value(&self, value: i32) -> Option<&EnumValue> { |
111 | unsafe { |
112 | let v = gobject_ffi::g_enum_get_value(self.0.as_ptr(), value); |
113 | if v.is_null() { |
114 | None |
115 | } else { |
116 | Some(&*(v as *const EnumValue)) |
117 | } |
118 | } |
119 | } |
120 | |
121 | // rustdoc-stripper-ignore-next |
122 | /// Gets `EnumValue` by string name `name`, if existing. |
123 | /// |
124 | /// Returns `None` if the enum does not contain any value |
125 | /// with name `name`. |
126 | #[doc (alias = "g_enum_get_value_by_name" )] |
127 | #[doc (alias = "get_value_by_name" )] |
128 | pub fn value_by_name(&self, name: &str) -> Option<&EnumValue> { |
129 | unsafe { |
130 | let v = gobject_ffi::g_enum_get_value_by_name(self.0.as_ptr(), name.to_glib_none().0); |
131 | if v.is_null() { |
132 | None |
133 | } else { |
134 | Some(&*(v as *const EnumValue)) |
135 | } |
136 | } |
137 | } |
138 | |
139 | // rustdoc-stripper-ignore-next |
140 | /// Gets `EnumValue` by string nick `nick`, if existing. |
141 | /// |
142 | /// Returns `None` if the enum does not contain any value |
143 | /// with nick `nick`. |
144 | #[doc (alias = "g_enum_get_value_by_nick" )] |
145 | #[doc (alias = "get_value_by_nick" )] |
146 | pub fn value_by_nick(&self, nick: &str) -> Option<&EnumValue> { |
147 | unsafe { |
148 | let v = gobject_ffi::g_enum_get_value_by_nick(self.0.as_ptr(), nick.to_glib_none().0); |
149 | if v.is_null() { |
150 | None |
151 | } else { |
152 | Some(&*(v as *const EnumValue)) |
153 | } |
154 | } |
155 | } |
156 | |
157 | // rustdoc-stripper-ignore-next |
158 | /// Gets all `EnumValue` of this `EnumClass`. |
159 | #[doc (alias = "get_values" )] |
160 | pub fn values(&self) -> &[EnumValue] { |
161 | unsafe { |
162 | if self.0.as_ref().n_values == 0 { |
163 | return &[]; |
164 | } |
165 | std::slice::from_raw_parts( |
166 | self.0.as_ref().values as *const EnumValue, |
167 | self.0.as_ref().n_values as usize, |
168 | ) |
169 | } |
170 | } |
171 | |
172 | // rustdoc-stripper-ignore-next |
173 | /// Converts integer `value` to a `Value`, if part of the enum. |
174 | pub fn to_value(&self, value: i32) -> Option<Value> { |
175 | self.value(value).map(|v| v.to_value(self)) |
176 | } |
177 | |
178 | // rustdoc-stripper-ignore-next |
179 | /// Converts string name `name` to a `Value`, if part of the enum. |
180 | pub fn to_value_by_name(&self, name: &str) -> Option<Value> { |
181 | self.value_by_name(name).map(|v| v.to_value(self)) |
182 | } |
183 | |
184 | // rustdoc-stripper-ignore-next |
185 | /// Converts string nick `nick` to a `Value`, if part of the enum. |
186 | pub fn to_value_by_nick(&self, nick: &str) -> Option<Value> { |
187 | self.value_by_nick(nick).map(|v| v.to_value(self)) |
188 | } |
189 | |
190 | // rustdoc-stripper-ignore-next |
191 | /// Complete `TypeInfo` for an enum with values. |
192 | /// This is an associated function. A method would result in a stack overflow due to a recurvice call: |
193 | /// callers should first create an `EnumClass` instance by calling `EnumClass::with_type()` which indirectly |
194 | /// calls `TypePluginRegisterImpl::register_dynamic_enum()` and `TypePluginImpl::complete_type_info()` |
195 | /// and one of them should call `EnumClass::with_type()` before calling this method. |
196 | /// `const_static_values` is a reference on a wrapper of a slice of `EnumValue`. |
197 | /// It must be static to ensure enumeration values are never dropped, and ensures that slice is terminated |
198 | /// by an `EnumValue` with all members being 0, as expected by GLib. |
199 | #[doc (alias = "g_enum_complete_type_info" )] |
200 | pub fn complete_type_info( |
201 | type_: Type, |
202 | const_static_values: &'static EnumValues, |
203 | ) -> Option<TypeInfo> { |
204 | unsafe { |
205 | let is_enum: bool = from_glib(gobject_ffi::g_type_is_a( |
206 | type_.into_glib(), |
207 | gobject_ffi::G_TYPE_ENUM, |
208 | )); |
209 | if !is_enum { |
210 | return None; |
211 | } |
212 | |
213 | let info = TypeInfo::default(); |
214 | gobject_ffi::g_enum_complete_type_info( |
215 | type_.into_glib(), |
216 | info.as_ptr(), |
217 | const_static_values.to_glib_none().0, |
218 | ); |
219 | Some(info) |
220 | } |
221 | } |
222 | } |
223 | |
224 | impl Drop for EnumClass { |
225 | #[inline ] |
226 | fn drop(&mut self) { |
227 | unsafe { |
228 | gobject_ffi::g_type_class_unref(self.0.as_ptr() as *mut _); |
229 | } |
230 | } |
231 | } |
232 | |
233 | impl Clone for EnumClass { |
234 | #[inline ] |
235 | fn clone(&self) -> Self { |
236 | unsafe { |
237 | Self(ptr::NonNull::new(ptr:gobject_ffi::g_type_class_ref(self.type_().into_glib()) as *mut _).unwrap()) |
238 | } |
239 | } |
240 | } |
241 | |
242 | // rustdoc-stripper-ignore-next |
243 | /// Representation of a single enum value of an `EnumClass`. |
244 | #[doc (alias = "GEnumValue" )] |
245 | #[derive (Copy, Clone)] |
246 | #[repr (transparent)] |
247 | pub struct EnumValue(gobject_ffi::GEnumValue); |
248 | |
249 | unsafe impl Send for EnumValue {} |
250 | unsafe impl Sync for EnumValue {} |
251 | |
252 | impl fmt::Debug for EnumValue { |
253 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
254 | f&mut DebugStruct<'_, '_>.debug_struct("EnumValue" ) |
255 | .field("value" , &self.value()) |
256 | .field("name" , &self.name()) |
257 | .field(name:"nick" , &self.nick()) |
258 | .finish() |
259 | } |
260 | } |
261 | |
262 | impl EnumValue { |
263 | // rustdoc-stripper-ignore-next |
264 | /// # Safety |
265 | /// |
266 | /// It is the responsibility of the caller to ensure `GEnumValue` is |
267 | /// valid. |
268 | pub const unsafe fn unsafe_from(g_value: gobject_ffi::GEnumValue) -> Self { |
269 | Self(g_value) |
270 | } |
271 | |
272 | // rustdoc-stripper-ignore-next |
273 | /// Get integer value corresponding to the value. |
274 | #[doc (alias = "get_value" )] |
275 | pub fn value(&self) -> i32 { |
276 | self.0.value |
277 | } |
278 | |
279 | // rustdoc-stripper-ignore-next |
280 | /// Get name corresponding to the value. |
281 | #[doc (alias = "get_name" )] |
282 | pub fn name(&self) -> &str { |
283 | unsafe { CStr::from_ptr(self.0.value_name).to_str().unwrap() } |
284 | } |
285 | |
286 | // rustdoc-stripper-ignore-next |
287 | /// Get nick corresponding to the value. |
288 | #[doc (alias = "get_nick" )] |
289 | pub fn nick(&self) -> &str { |
290 | unsafe { CStr::from_ptr(self.0.value_nick).to_str().unwrap() } |
291 | } |
292 | |
293 | // rustdoc-stripper-ignore-next |
294 | /// Convert enum value to a `Value`. |
295 | pub fn to_value(&self, enum_: &EnumClass) -> Value { |
296 | unsafe { |
297 | let mut v = Value::from_type_unchecked(enum_.type_()); |
298 | gobject_ffi::g_value_set_enum(v.to_glib_none_mut().0, self.0.value); |
299 | v |
300 | } |
301 | } |
302 | |
303 | // rustdoc-stripper-ignore-next |
304 | /// Convert enum value from a `Value`. |
305 | pub fn from_value(value: &Value) -> Option<(EnumClass, &EnumValue)> { |
306 | unsafe { |
307 | let enum_class = EnumClass::with_type(value.type_())?; |
308 | let v = enum_class.value(gobject_ffi::g_value_get_enum(value.to_glib_none().0))?; |
309 | let v = &*(v as *const EnumValue); |
310 | Some((enum_class, v)) |
311 | } |
312 | } |
313 | } |
314 | |
315 | impl PartialEq for EnumValue { |
316 | fn eq(&self, other: &Self) -> bool { |
317 | self.value().eq(&other.value()) |
318 | } |
319 | } |
320 | |
321 | impl Eq for EnumValue {} |
322 | |
323 | impl PartialOrd for EnumValue { |
324 | fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { |
325 | Some(self.cmp(other)) |
326 | } |
327 | } |
328 | |
329 | impl Ord for EnumValue { |
330 | fn cmp(&self, other: &Self) -> cmp::Ordering { |
331 | self.value().cmp(&other.value()) |
332 | } |
333 | } |
334 | |
335 | impl UnsafeFrom<gobject_ffi::GEnumValue> for EnumValue { |
336 | unsafe fn unsafe_from(g_value: gobject_ffi::GEnumValue) -> Self { |
337 | Self::unsafe_from(g_value) |
338 | } |
339 | } |
340 | |
341 | unsafe impl<'a> crate::value::FromValue<'a> for &EnumValue { |
342 | type Checker = EnumTypeChecker; |
343 | |
344 | unsafe fn from_value(value: &'a Value) -> Self { |
345 | let (_, v: &EnumValue) = EnumValue::from_value(value).unwrap(); |
346 | // SAFETY: The enum class and its values live forever |
347 | std::mem::transmute(src:v) |
348 | } |
349 | } |
350 | |
351 | // rustdoc-stripper-ignore-next |
352 | /// Define the zero value and the associated GLib type. |
353 | impl EnumerationValue<EnumValue> for EnumValue { |
354 | type GlibType = gobject_ffi::GEnumValue; |
355 | const ZERO: EnumValue = unsafe { |
356 | EnumValue::unsafe_from(g_value:gobject_ffi::GEnumValue { |
357 | value: 0, |
358 | value_name: ptr::null(), |
359 | value_nick: ptr::null(), |
360 | }) |
361 | }; |
362 | } |
363 | |
364 | // rustdoc-stripper-ignore-next |
365 | /// Storage of enum values. |
366 | pub type EnumValuesStorage<const N: usize> = EnumerationValuesStorage<EnumValue, N>; |
367 | |
368 | // rustdoc-stripper-ignore-next |
369 | /// Representation of enum values wrapped by `EnumValuesStorage` |
370 | pub type EnumValues = EnumerationValues<EnumValue>; |
371 | |
372 | pub struct EnumTypeChecker(); |
373 | unsafe impl crate::value::ValueTypeChecker for EnumTypeChecker { |
374 | type Error = InvalidEnumError; |
375 | |
376 | fn check(value: &Value) -> Result<(), Self::Error> { |
377 | let t: Type = value.type_(); |
378 | if t.is_a(Type::ENUM) { |
379 | Ok(()) |
380 | } else { |
381 | Err(InvalidEnumError) |
382 | } |
383 | } |
384 | } |
385 | |
386 | // rustdoc-stripper-ignore-next |
387 | /// An error returned from the [`get`](struct.Value.html#method.get) function |
388 | /// on a [`Value`](struct.Value.html) for enum types. |
389 | #[derive (Clone, PartialEq, Eq, Debug)] |
390 | pub struct InvalidEnumError; |
391 | |
392 | impl fmt::Display for InvalidEnumError { |
393 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
394 | write!(f, "Value is not an enum" ) |
395 | } |
396 | } |
397 | |
398 | impl std::error::Error for InvalidEnumError {} |
399 | |
400 | // rustdoc-stripper-ignore-next |
401 | /// Representation of a `flags` for dynamically, at runtime, querying the values of the enum and |
402 | /// using them |
403 | #[doc (alias = "GFlagsClass" )] |
404 | #[repr (transparent)] |
405 | pub struct FlagsClass(ptr::NonNull<gobject_ffi::GFlagsClass>); |
406 | |
407 | unsafe impl Send for FlagsClass {} |
408 | unsafe impl Sync for FlagsClass {} |
409 | |
410 | impl fmt::Debug for FlagsClass { |
411 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
412 | f&mut DebugStruct<'_, '_>.debug_struct("FlagsClass" ) |
413 | .field("type" , &self.type_()) |
414 | .field(name:"values" , &self.values()) |
415 | .finish() |
416 | } |
417 | } |
418 | |
419 | impl FlagsClass { |
420 | // rustdoc-stripper-ignore-next |
421 | /// Create a new `FlagsClass` from a static type `T`. |
422 | /// |
423 | /// Panics if `T` is not representing an flags type. |
424 | pub fn new<T: StaticType + HasParamSpec<ParamSpec = ParamSpecFlags>>() -> Self { |
425 | Self::with_type(T::static_type()).expect("invalid flags class" ) |
426 | } |
427 | // rustdoc-stripper-ignore-next |
428 | /// Create a new `FlagsClass` from a `Type` |
429 | /// |
430 | /// Returns `None` if `type_` is not representing a flags type. |
431 | pub fn with_type(type_: Type) -> Option<Self> { |
432 | unsafe { |
433 | let is_flags: bool = from_glib(gobject_ffi::g_type_is_a( |
434 | type_.into_glib(), |
435 | gobject_ffi::G_TYPE_FLAGS, |
436 | )); |
437 | if !is_flags { |
438 | return None; |
439 | } |
440 | |
441 | Some(FlagsClass( |
442 | ptr::NonNull::new(gobject_ffi::g_type_class_ref(type_.into_glib()) as *mut _) |
443 | .unwrap(), |
444 | )) |
445 | } |
446 | } |
447 | |
448 | // rustdoc-stripper-ignore-next |
449 | /// `Type` of the flags. |
450 | pub fn type_(&self) -> Type { |
451 | unsafe { from_glib(self.0.as_ref().g_type_class.g_type) } |
452 | } |
453 | |
454 | // rustdoc-stripper-ignore-next |
455 | /// Gets `FlagsValue` by integer `value`, if existing. |
456 | /// |
457 | /// Returns `None` if the flags do not contain any value |
458 | /// with `value`. |
459 | #[doc (alias = "g_flags_get_first_value" )] |
460 | #[doc (alias = "get_value" )] |
461 | pub fn value(&self, value: u32) -> Option<&FlagsValue> { |
462 | unsafe { |
463 | let v = gobject_ffi::g_flags_get_first_value(self.0.as_ptr(), value); |
464 | if v.is_null() { |
465 | None |
466 | } else { |
467 | Some(&*(v as *const FlagsValue)) |
468 | } |
469 | } |
470 | } |
471 | |
472 | // rustdoc-stripper-ignore-next |
473 | /// Gets `FlagsValue` by string name `name`, if existing. |
474 | /// |
475 | /// Returns `None` if the flags do not contain any value |
476 | /// with name `name`. |
477 | #[doc (alias = "g_flags_get_value_by_name" )] |
478 | #[doc (alias = "get_value_by_name" )] |
479 | pub fn value_by_name(&self, name: &str) -> Option<&FlagsValue> { |
480 | unsafe { |
481 | let v = gobject_ffi::g_flags_get_value_by_name(self.0.as_ptr(), name.to_glib_none().0); |
482 | if v.is_null() { |
483 | None |
484 | } else { |
485 | Some(&*(v as *const FlagsValue)) |
486 | } |
487 | } |
488 | } |
489 | |
490 | // rustdoc-stripper-ignore-next |
491 | /// Gets `FlagsValue` by string nick `nick`, if existing. |
492 | /// |
493 | /// Returns `None` if the flags do not contain any value |
494 | /// with nick `nick`. |
495 | #[doc (alias = "g_flags_get_value_by_nick" )] |
496 | #[doc (alias = "get_value_by_nick" )] |
497 | pub fn value_by_nick(&self, nick: &str) -> Option<&FlagsValue> { |
498 | unsafe { |
499 | let v = gobject_ffi::g_flags_get_value_by_nick(self.0.as_ptr(), nick.to_glib_none().0); |
500 | if v.is_null() { |
501 | None |
502 | } else { |
503 | Some(&*(v as *const FlagsValue)) |
504 | } |
505 | } |
506 | } |
507 | |
508 | // rustdoc-stripper-ignore-next |
509 | /// Gets all `FlagsValue` of this `FlagsClass`. |
510 | #[doc (alias = "get_values" )] |
511 | pub fn values(&self) -> &[FlagsValue] { |
512 | unsafe { |
513 | if self.0.as_ref().n_values == 0 { |
514 | return &[]; |
515 | } |
516 | std::slice::from_raw_parts( |
517 | self.0.as_ref().values as *const FlagsValue, |
518 | self.0.as_ref().n_values as usize, |
519 | ) |
520 | } |
521 | } |
522 | |
523 | // rustdoc-stripper-ignore-next |
524 | /// Converts integer `value` to a `Value`, if part of the flags. |
525 | pub fn to_value(&self, value: u32) -> Option<Value> { |
526 | self.value(value).map(|v| v.to_value(self)) |
527 | } |
528 | |
529 | // rustdoc-stripper-ignore-next |
530 | /// Converts string name `name` to a `Value`, if part of the flags. |
531 | pub fn to_value_by_name(&self, name: &str) -> Option<Value> { |
532 | self.value_by_name(name).map(|v| v.to_value(self)) |
533 | } |
534 | |
535 | // rustdoc-stripper-ignore-next |
536 | /// Converts string nick `nick` to a `Value`, if part of the flags. |
537 | pub fn to_value_by_nick(&self, nick: &str) -> Option<Value> { |
538 | self.value_by_nick(nick).map(|v| v.to_value(self)) |
539 | } |
540 | |
541 | // rustdoc-stripper-ignore-next |
542 | /// Checks if the flags corresponding to integer `f` is set in `value`. |
543 | pub fn is_set(&self, value: &Value, f: u32) -> bool { |
544 | unsafe { |
545 | if self.type_() != value.type_() { |
546 | return false; |
547 | } |
548 | |
549 | let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0); |
550 | flags & f != 0 |
551 | } |
552 | } |
553 | |
554 | // rustdoc-stripper-ignore-next |
555 | /// Checks if the flags corresponding to string name `name` is set in `value`. |
556 | pub fn is_set_by_name(&self, value: &Value, name: &str) -> bool { |
557 | unsafe { |
558 | if self.type_() != value.type_() { |
559 | return false; |
560 | } |
561 | |
562 | if let Some(f) = self.value_by_name(name) { |
563 | let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0); |
564 | flags & f.value() != 0 |
565 | } else { |
566 | false |
567 | } |
568 | } |
569 | } |
570 | |
571 | // rustdoc-stripper-ignore-next |
572 | /// Checks if the flags corresponding to string nick `nick` is set in `value`. |
573 | pub fn is_set_by_nick(&self, value: &Value, nick: &str) -> bool { |
574 | unsafe { |
575 | if self.type_() != value.type_() { |
576 | return false; |
577 | } |
578 | |
579 | if let Some(f) = self.value_by_nick(nick) { |
580 | let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0); |
581 | flags & f.value() != 0 |
582 | } else { |
583 | false |
584 | } |
585 | } |
586 | } |
587 | |
588 | // rustdoc-stripper-ignore-next |
589 | /// Set flags value corresponding to integer `f` in `value`, if part of that flags. If the |
590 | /// flag is already set, it will succeed without doing any changes. |
591 | /// |
592 | /// Returns `Ok(value)` with the flag set if successful, or `Err(value)` with the original |
593 | /// value otherwise. |
594 | #[doc (alias = "g_value_set_flags" )] |
595 | pub fn set(&self, mut value: Value, f: u32) -> Result<Value, Value> { |
596 | unsafe { |
597 | if self.type_() != value.type_() { |
598 | return Err(value); |
599 | } |
600 | |
601 | if let Some(f) = self.value(f) { |
602 | let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0); |
603 | gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value()); |
604 | Ok(value) |
605 | } else { |
606 | Err(value) |
607 | } |
608 | } |
609 | } |
610 | |
611 | // rustdoc-stripper-ignore-next |
612 | /// Set flags value corresponding to string name `name` in `value`, if part of that flags. |
613 | /// If the flag is already set, it will succeed without doing any changes. |
614 | /// |
615 | /// Returns `Ok(value)` with the flag set if successful, or `Err(value)` with the original |
616 | /// value otherwise. |
617 | pub fn set_by_name(&self, mut value: Value, name: &str) -> Result<Value, Value> { |
618 | unsafe { |
619 | if self.type_() != value.type_() { |
620 | return Err(value); |
621 | } |
622 | |
623 | if let Some(f) = self.value_by_name(name) { |
624 | let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0); |
625 | gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value()); |
626 | Ok(value) |
627 | } else { |
628 | Err(value) |
629 | } |
630 | } |
631 | } |
632 | |
633 | // rustdoc-stripper-ignore-next |
634 | /// Set flags value corresponding to string nick `nick` in `value`, if part of that flags. |
635 | /// If the flag is already set, it will succeed without doing any changes. |
636 | /// |
637 | /// Returns `Ok(value)` with the flag set if successful, or `Err(value)` with the original |
638 | /// value otherwise. |
639 | pub fn set_by_nick(&self, mut value: Value, nick: &str) -> Result<Value, Value> { |
640 | unsafe { |
641 | if self.type_() != value.type_() { |
642 | return Err(value); |
643 | } |
644 | |
645 | if let Some(f) = self.value_by_nick(nick) { |
646 | let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0); |
647 | gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value()); |
648 | Ok(value) |
649 | } else { |
650 | Err(value) |
651 | } |
652 | } |
653 | } |
654 | |
655 | // rustdoc-stripper-ignore-next |
656 | /// Unset flags value corresponding to integer `f` in `value`, if part of that flags. |
657 | /// If the flag is already unset, it will succeed without doing any changes. |
658 | /// |
659 | /// Returns `Ok(value)` with the flag unset if successful, or `Err(value)` with the original |
660 | /// value otherwise. |
661 | pub fn unset(&self, mut value: Value, f: u32) -> Result<Value, Value> { |
662 | unsafe { |
663 | if self.type_() != value.type_() { |
664 | return Err(value); |
665 | } |
666 | |
667 | if let Some(f) = self.value(f) { |
668 | let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0); |
669 | gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value()); |
670 | Ok(value) |
671 | } else { |
672 | Err(value) |
673 | } |
674 | } |
675 | } |
676 | |
677 | // rustdoc-stripper-ignore-next |
678 | /// Unset flags value corresponding to string name `name` in `value`, if part of that flags. |
679 | /// If the flag is already unset, it will succeed without doing any changes. |
680 | /// |
681 | /// Returns `Ok(value)` with the flag unset if successful, or `Err(value)` with the original |
682 | /// value otherwise. |
683 | pub fn unset_by_name(&self, mut value: Value, name: &str) -> Result<Value, Value> { |
684 | unsafe { |
685 | if self.type_() != value.type_() { |
686 | return Err(value); |
687 | } |
688 | |
689 | if let Some(f) = self.value_by_name(name) { |
690 | let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0); |
691 | gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value()); |
692 | Ok(value) |
693 | } else { |
694 | Err(value) |
695 | } |
696 | } |
697 | } |
698 | |
699 | // rustdoc-stripper-ignore-next |
700 | /// Unset flags value corresponding to string nick `nick` in `value`, if part of that flags. |
701 | /// If the flag is already unset, it will succeed without doing any changes. |
702 | /// |
703 | /// Returns `Ok(value)` with the flag unset if successful, or `Err(value)` with the original |
704 | /// value otherwise. |
705 | pub fn unset_by_nick(&self, mut value: Value, nick: &str) -> Result<Value, Value> { |
706 | unsafe { |
707 | if self.type_() != value.type_() { |
708 | return Err(value); |
709 | } |
710 | |
711 | if let Some(f) = self.value_by_nick(nick) { |
712 | let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0); |
713 | gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value()); |
714 | Ok(value) |
715 | } else { |
716 | Err(value) |
717 | } |
718 | } |
719 | } |
720 | |
721 | // rustdoc-stripper-ignore-next |
722 | /// Converts an integer `value` to a string of nicks separated by `|`. |
723 | pub fn to_nick_string(&self, mut value: u32) -> String { |
724 | let mut s = String::new(); |
725 | for val in self.values() { |
726 | let v = val.value(); |
727 | if v != 0 && (value & v) == v { |
728 | value &= !v; |
729 | if !s.is_empty() { |
730 | s.push('|' ); |
731 | } |
732 | s.push_str(val.nick()); |
733 | } |
734 | } |
735 | s |
736 | } |
737 | |
738 | // rustdoc-stripper-ignore-next |
739 | /// Converts a string of nicks `s` separated by `|` to an integer value. |
740 | pub fn from_nick_string(&self, s: &str) -> Result<u32, ParseFlagsError> { |
741 | s.split('|' ).try_fold(0u32, |acc, flag| { |
742 | self.value_by_nick(flag.trim()) |
743 | .map(|v| acc + v.value()) |
744 | .ok_or_else(|| ParseFlagsError(flag.to_owned())) |
745 | }) |
746 | } |
747 | |
748 | // rustdoc-stripper-ignore-next |
749 | /// Returns a new `FlagsBuilder` for conveniently setting/unsetting flags |
750 | /// and building a `Value`. |
751 | pub fn builder(&self) -> FlagsBuilder { |
752 | FlagsBuilder::new(self) |
753 | } |
754 | |
755 | // rustdoc-stripper-ignore-next |
756 | /// Returns a new `FlagsBuilder` for conveniently setting/unsetting flags |
757 | /// and building a `Value`. The `Value` is initialized with `value`. |
758 | pub fn builder_with_value(&self, value: Value) -> Option<FlagsBuilder> { |
759 | if self.type_() != value.type_() { |
760 | return None; |
761 | } |
762 | |
763 | Some(FlagsBuilder::with_value(self, value)) |
764 | } |
765 | |
766 | // rustdoc-stripper-ignore-next |
767 | /// Complete `TypeInfo` for the flags with values. |
768 | /// This is an associated function. A method would result in a stack overflow due to a recurvice call: |
769 | /// callers should first create an `FlagsClass` instance by calling `FlagsClass::with_type()` which indirectly |
770 | /// calls `TypePluginRegisterImpl::register_dynamic_flags()` and `TypePluginImpl::complete_type_info()` |
771 | /// and one of them should call `FlagsClass::with_type()` before calling this method. |
772 | /// `const_static_values` is a reference on a wrapper of a slice of `FlagsValue`. |
773 | /// It must be static to ensure flags values are never dropped, and ensures that slice is terminated |
774 | /// by an `FlagsValue` with all members being 0, as expected by GLib. |
775 | #[doc (alias = "g_flags_complete_type_info" )] |
776 | pub fn complete_type_info( |
777 | type_: Type, |
778 | const_static_values: &'static FlagsValues, |
779 | ) -> Option<TypeInfo> { |
780 | unsafe { |
781 | let is_flags: bool = from_glib(gobject_ffi::g_type_is_a( |
782 | type_.into_glib(), |
783 | gobject_ffi::G_TYPE_FLAGS, |
784 | )); |
785 | if !is_flags { |
786 | return None; |
787 | } |
788 | |
789 | let info = TypeInfo::default(); |
790 | gobject_ffi::g_flags_complete_type_info( |
791 | type_.into_glib(), |
792 | info.as_ptr(), |
793 | const_static_values.to_glib_none().0, |
794 | ); |
795 | Some(info) |
796 | } |
797 | } |
798 | } |
799 | |
800 | impl Drop for FlagsClass { |
801 | #[inline ] |
802 | fn drop(&mut self) { |
803 | unsafe { |
804 | gobject_ffi::g_type_class_unref(self.0.as_ptr() as *mut _); |
805 | } |
806 | } |
807 | } |
808 | |
809 | impl Clone for FlagsClass { |
810 | #[inline ] |
811 | fn clone(&self) -> Self { |
812 | unsafe { |
813 | Self(ptr::NonNull::new(ptr:gobject_ffi::g_type_class_ref(self.type_().into_glib()) as *mut _).unwrap()) |
814 | } |
815 | } |
816 | } |
817 | |
818 | #[derive (Debug)] |
819 | pub struct ParseFlagsError(String); |
820 | |
821 | impl std::error::Error for ParseFlagsError {} |
822 | |
823 | impl fmt::Display for ParseFlagsError { |
824 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
825 | write!(f, "Unknown flag: ' {}'" , self.0) |
826 | } |
827 | } |
828 | |
829 | impl ParseFlagsError { |
830 | pub fn flag(&self) -> &str { |
831 | &self.0 |
832 | } |
833 | } |
834 | |
835 | // rustdoc-stripper-ignore-next |
836 | /// Representation of a single flags value of a `FlagsClass`. |
837 | #[doc (alias = "GFlagsValue" )] |
838 | #[derive (Copy, Clone)] |
839 | #[repr (transparent)] |
840 | pub struct FlagsValue(gobject_ffi::GFlagsValue); |
841 | |
842 | unsafe impl Send for FlagsValue {} |
843 | unsafe impl Sync for FlagsValue {} |
844 | |
845 | impl fmt::Debug for FlagsValue { |
846 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
847 | f&mut DebugStruct<'_, '_>.debug_struct("FlagsValue" ) |
848 | .field("value" , &self.value()) |
849 | .field("name" , &self.name()) |
850 | .field(name:"nick" , &self.nick()) |
851 | .finish() |
852 | } |
853 | } |
854 | |
855 | impl FlagsValue { |
856 | // rustdoc-stripper-ignore-next |
857 | /// # Safety |
858 | /// |
859 | /// It is the responsibility of the caller to ensure `GFlagsValue` is |
860 | /// valid. |
861 | pub const unsafe fn unsafe_from(g_value: gobject_ffi::GFlagsValue) -> Self { |
862 | Self(g_value) |
863 | } |
864 | |
865 | // rustdoc-stripper-ignore-next |
866 | /// Get integer value corresponding to the value. |
867 | #[doc (alias = "get_value" )] |
868 | pub fn value(&self) -> u32 { |
869 | self.0.value |
870 | } |
871 | |
872 | // rustdoc-stripper-ignore-next |
873 | /// Get name corresponding to the value. |
874 | #[doc (alias = "get_name" )] |
875 | pub fn name(&self) -> &str { |
876 | unsafe { CStr::from_ptr(self.0.value_name).to_str().unwrap() } |
877 | } |
878 | |
879 | // rustdoc-stripper-ignore-next |
880 | /// Get nick corresponding to the value. |
881 | #[doc (alias = "get_nick" )] |
882 | pub fn nick(&self) -> &str { |
883 | unsafe { CStr::from_ptr(self.0.value_nick).to_str().unwrap() } |
884 | } |
885 | |
886 | // rustdoc-stripper-ignore-next |
887 | /// Convert flags value to a `Value`. |
888 | pub fn to_value(&self, flags: &FlagsClass) -> Value { |
889 | unsafe { |
890 | let mut v = Value::from_type_unchecked(flags.type_()); |
891 | gobject_ffi::g_value_set_flags(v.to_glib_none_mut().0, self.0.value); |
892 | v |
893 | } |
894 | } |
895 | |
896 | // rustdoc-stripper-ignore-next |
897 | /// Convert flags values from a `Value`. This returns all flags that are set. |
898 | pub fn from_value(value: &Value) -> Option<(FlagsClass, Vec<&FlagsValue>)> { |
899 | unsafe { |
900 | let flags_class = FlagsClass::with_type(value.type_())?; |
901 | let mut res = Vec::new(); |
902 | let f = gobject_ffi::g_value_get_flags(value.to_glib_none().0); |
903 | for v in flags_class.values() { |
904 | if v.value() & f != 0 { |
905 | res.push(&*(v as *const FlagsValue)); |
906 | } |
907 | } |
908 | Some((flags_class, res)) |
909 | } |
910 | } |
911 | } |
912 | |
913 | impl PartialEq for FlagsValue { |
914 | fn eq(&self, other: &Self) -> bool { |
915 | self.value().eq(&other.value()) |
916 | } |
917 | } |
918 | |
919 | impl Eq for FlagsValue {} |
920 | |
921 | impl UnsafeFrom<gobject_ffi::GFlagsValue> for FlagsValue { |
922 | unsafe fn unsafe_from(g_value: gobject_ffi::GFlagsValue) -> Self { |
923 | Self::unsafe_from(g_value) |
924 | } |
925 | } |
926 | |
927 | // rustdoc-stripper-ignore-next |
928 | /// Define the zero value and the associated GLib type. |
929 | impl EnumerationValue<FlagsValue> for FlagsValue { |
930 | type GlibType = gobject_ffi::GFlagsValue; |
931 | const ZERO: FlagsValue = unsafe { |
932 | FlagsValue::unsafe_from(g_value:gobject_ffi::GFlagsValue { |
933 | value: 0, |
934 | value_name: ptr::null(), |
935 | value_nick: ptr::null(), |
936 | }) |
937 | }; |
938 | } |
939 | |
940 | // rustdoc-stripper-ignore-next |
941 | /// Storage of flags values. |
942 | pub type FlagsValuesStorage<const N: usize> = EnumerationValuesStorage<FlagsValue, N>; |
943 | |
944 | // rustdoc-stripper-ignore-next |
945 | /// Representation of flags values wrapped by `FlagsValuesStorage` |
946 | pub type FlagsValues = EnumerationValues<FlagsValue>; |
947 | |
948 | // rustdoc-stripper-ignore-next |
949 | /// Builder for conveniently setting/unsetting flags and returning a `Value`. |
950 | /// |
951 | /// Example for getting a flags property, unsetting some flags and setting the updated flags on the |
952 | /// object again: |
953 | /// |
954 | /// ```ignore |
955 | /// let flags = obj.property("flags" ).unwrap(); |
956 | /// let flags_class = FlagsClass::new(flags.type_()).unwrap(); |
957 | /// let flags = flags_class.builder_with_value(flags).unwrap() |
958 | /// .unset_by_nick("some-flag" ) |
959 | /// .unset_by_nick("some-other-flag" ) |
960 | /// .build() |
961 | /// .unwrap(); |
962 | /// obj.set_property("flags" , &flags).unwrap(); |
963 | /// ``` |
964 | /// |
965 | /// If setting/unsetting any value fails, `build()` returns `None`. |
966 | #[must_use = "The builder must be built to be used" ] |
967 | pub struct FlagsBuilder<'a>(&'a FlagsClass, Option<Value>); |
968 | impl FlagsBuilder<'_> { |
969 | fn new(flags_class: &FlagsClass) -> FlagsBuilder { |
970 | let value = unsafe { Value::from_type_unchecked(flags_class.type_()) }; |
971 | FlagsBuilder(flags_class, Some(value)) |
972 | } |
973 | |
974 | fn with_value(flags_class: &FlagsClass, value: Value) -> FlagsBuilder { |
975 | FlagsBuilder(flags_class, Some(value)) |
976 | } |
977 | |
978 | // rustdoc-stripper-ignore-next |
979 | /// Set flags corresponding to integer value `f`. |
980 | pub fn set(mut self, f: u32) -> Self { |
981 | if let Some(value) = self.1.take() { |
982 | self.1 = self.0.set(value, f).ok(); |
983 | } |
984 | |
985 | self |
986 | } |
987 | |
988 | // rustdoc-stripper-ignore-next |
989 | /// Set flags corresponding to string name `name`. |
990 | pub fn set_by_name(mut self, name: &str) -> Self { |
991 | if let Some(value) = self.1.take() { |
992 | self.1 = self.0.set_by_name(value, name).ok(); |
993 | } |
994 | |
995 | self |
996 | } |
997 | |
998 | // rustdoc-stripper-ignore-next |
999 | /// Set flags corresponding to string nick `nick`. |
1000 | pub fn set_by_nick(mut self, nick: &str) -> Self { |
1001 | if let Some(value) = self.1.take() { |
1002 | self.1 = self.0.set_by_nick(value, nick).ok(); |
1003 | } |
1004 | |
1005 | self |
1006 | } |
1007 | |
1008 | // rustdoc-stripper-ignore-next |
1009 | /// Unsets flags corresponding to integer value `f`. |
1010 | pub fn unset(mut self, f: u32) -> Self { |
1011 | if let Some(value) = self.1.take() { |
1012 | self.1 = self.0.unset(value, f).ok(); |
1013 | } |
1014 | |
1015 | self |
1016 | } |
1017 | |
1018 | // rustdoc-stripper-ignore-next |
1019 | /// Unset flags corresponding to string name `name`. |
1020 | pub fn unset_by_name(mut self, name: &str) -> Self { |
1021 | if let Some(value) = self.1.take() { |
1022 | self.1 = self.0.unset_by_name(value, name).ok(); |
1023 | } |
1024 | |
1025 | self |
1026 | } |
1027 | |
1028 | // rustdoc-stripper-ignore-next |
1029 | /// Unset flags corresponding to string nick `nick`. |
1030 | pub fn unset_by_nick(mut self, nick: &str) -> Self { |
1031 | if let Some(value) = self.1.take() { |
1032 | self.1 = self.0.unset_by_nick(value, nick).ok(); |
1033 | } |
1034 | |
1035 | self |
1036 | } |
1037 | |
1038 | // rustdoc-stripper-ignore-next |
1039 | /// Converts to the final `Value`, unless any previous setting/unsetting of flags failed. |
1040 | #[must_use = "Value returned from the builder should probably be used" ] |
1041 | pub fn build(self) -> Option<Value> { |
1042 | self.1 |
1043 | } |
1044 | } |
1045 | |
1046 | unsafe impl<'a> crate::value::FromValue<'a> for Vec<&FlagsValue> { |
1047 | type Checker = FlagsTypeChecker; |
1048 | |
1049 | unsafe fn from_value(value: &'a Value) -> Self { |
1050 | let (_, v: Vec<&FlagsValue>) = FlagsValue::from_value(value).unwrap(); |
1051 | // SAFETY: The enum class and its values live forever |
1052 | std::mem::transmute(src:v) |
1053 | } |
1054 | } |
1055 | |
1056 | pub struct FlagsTypeChecker(); |
1057 | unsafe impl crate::value::ValueTypeChecker for FlagsTypeChecker { |
1058 | type Error = InvalidFlagsError; |
1059 | |
1060 | fn check(value: &Value) -> Result<(), Self::Error> { |
1061 | let t: Type = value.type_(); |
1062 | if t.is_a(Type::FLAGS) { |
1063 | Ok(()) |
1064 | } else { |
1065 | Err(InvalidFlagsError) |
1066 | } |
1067 | } |
1068 | } |
1069 | |
1070 | // rustdoc-stripper-ignore-next |
1071 | /// An error returned from the [`get`](struct.Value.html#method.get) function |
1072 | /// on a [`Value`](struct.Value.html) for flags types. |
1073 | #[derive (Clone, PartialEq, Eq, Debug)] |
1074 | pub struct InvalidFlagsError; |
1075 | |
1076 | impl fmt::Display for InvalidFlagsError { |
1077 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
1078 | write!(f, "Value is not a flags" ) |
1079 | } |
1080 | } |
1081 | |
1082 | impl std::error::Error for InvalidFlagsError {} |
1083 | |
1084 | // rustdoc-stripper-ignore-next |
1085 | /// helper trait to define the zero value and the associated GLib type. |
1086 | pub trait EnumerationValue<E>: Copy { |
1087 | type GlibType; |
1088 | const ZERO: E; |
1089 | } |
1090 | |
1091 | // rustdoc-stripper-ignore-next |
1092 | /// Storage of enumeration values terminated by a zero value. Should be used |
1093 | /// only as a storage location for `EnumValue` or `FlagsValue` when registering |
1094 | /// an enum or flags as a dynamic type. |
1095 | /// see `TypePluginRegisterImpl::register_dynamic_enum()`, `TypePluginRegisterImpl::register_dynamic_flags()` |
1096 | /// and `TypePluginImpl::complete_type_info()`. |
1097 | /// Inner is intentionally private to ensure other modules will not access the |
1098 | /// enum (or flags) values by this way. |
1099 | /// Use `EnumClass::values()` or `EnumClass::value()` to get the enum values. |
1100 | /// Use `FlagsClass::values()` or `FlagsClass::value()` to get the flags values. |
1101 | #[repr (C)] |
1102 | pub struct EnumerationValuesStorage<E: EnumerationValue<E>, const S: usize>([E; S]); |
1103 | |
1104 | impl<E: EnumerationValue<E>, const S: usize> EnumerationValuesStorage<E, S> { |
1105 | // rustdoc-stripper-ignore-next |
1106 | /// creates a new `EnumerationValuesStorage` with the given values and a final zero value. |
1107 | pub const fn new<const N: usize>(values: [E; N]) -> Self { |
1108 | #[repr (C)] |
1109 | #[derive (Copy, Clone)] |
1110 | struct Both<E: Copy, const N: usize>([E; N], [E; 1]); |
1111 | |
1112 | #[repr (C)] |
1113 | union Transmute<E: Copy, const N: usize, const S: usize> { |
1114 | from: Both<E, N>, |
1115 | to: [E; S], |
1116 | } |
1117 | |
1118 | // SAFETY: Transmute is repr(C) and union fields are compatible in terms of size and alignment, so the access to union fields is safe. |
1119 | unsafe { |
1120 | // create an array with the values and terminated by a zero value. |
1121 | let all = Transmute { |
1122 | from: Both(values, [E::ZERO; 1]), |
1123 | } |
1124 | .to; |
1125 | Self(all) |
1126 | } |
1127 | } |
1128 | } |
1129 | |
1130 | impl<E: EnumerationValue<E>, const S: usize> AsRef<EnumerationValues<E>> |
1131 | for EnumerationValuesStorage<E, S> |
1132 | { |
1133 | fn as_ref(&self) -> &EnumerationValues<E> { |
1134 | // SAFETY: EnumerationStorage and EnumerationValues are repr(C) and their unique field are compatible (array and slice of the same type), so the cast is safe. |
1135 | unsafe { &*(&self.0 as *const [E] as *const EnumerationValues<E>) } |
1136 | } |
1137 | } |
1138 | |
1139 | // rustdoc-stripper-ignore-next |
1140 | /// Representation of enumeration values wrapped by `EnumerationValuesStorage`. |
1141 | /// Easier to use because don't have a size parameter to be specify. Should be |
1142 | /// used only to register an enum or flags as a dynamic type. |
1143 | /// see `TypePluginRegisterImpl::register_dynamic_enum()`, `TypePluginRegisterImpl::register_dynamic_flags()` |
1144 | /// and `TypePluginImpl::complete_type_info()`. |
1145 | /// Field is intentionally private to ensure other modules will not access the |
1146 | /// enum (or flags) values by this way. |
1147 | /// Use `EnumClass::values()` or `EnumClass::value()` to get the enum values. |
1148 | /// Use `FlagsClass::values()` or `FlagsClass::value()` to get the flags values. |
1149 | #[repr (C)] |
1150 | pub struct EnumerationValues<E: EnumerationValue<E>>([E]); |
1151 | |
1152 | impl<E: EnumerationValue<E>> Deref for EnumerationValues<E> { |
1153 | type Target = [E]; |
1154 | |
1155 | // rustdoc-stripper-ignore-next |
1156 | /// Dereferences the enumeration values as a slice, but excluding the last value which is zero. |
1157 | fn deref(&self) -> &Self::Target { |
1158 | // SAFETY: EnumerationValues contains at least the zero value which terminates the array. |
1159 | unsafe { std::slice::from_raw_parts(self.0.as_ptr(), self.0.len() - 1) } |
1160 | } |
1161 | } |
1162 | |
1163 | #[doc (hidden)] |
1164 | impl<'a, E: 'a + EnumerationValue<E>> ToGlibPtr<'a, *const E::GlibType> for EnumerationValues<E> { |
1165 | type Storage = &'a Self; |
1166 | |
1167 | fn to_glib_none(&'a self) -> Stash<'a, *const E::GlibType, Self> { |
1168 | Stash(self.0.as_ptr() as *const E::GlibType, self) |
1169 | } |
1170 | } |
1171 | |
1172 | #[cfg (test)] |
1173 | mod tests { |
1174 | use super::*; |
1175 | |
1176 | #[test ] |
1177 | fn test_flags() { |
1178 | let flags = FlagsClass::new::<crate::BindingFlags>(); |
1179 | let values = flags.values(); |
1180 | let def1 = values |
1181 | .iter() |
1182 | .find(|v| v.name() == "G_BINDING_DEFAULT" ) |
1183 | .unwrap(); |
1184 | let def2 = flags.value_by_name("G_BINDING_DEFAULT" ).unwrap(); |
1185 | assert!(ptr::eq(def1, def2)); |
1186 | |
1187 | let value = flags.to_value(0).unwrap(); |
1188 | let values = value.get::<Vec<&FlagsValue>>().unwrap(); |
1189 | assert_eq!(values.len(), 0); |
1190 | |
1191 | assert_eq!(def1.value(), crate::BindingFlags::DEFAULT.bits()); |
1192 | } |
1193 | } |
1194 | |