1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{cmp, ffi::CStr, fmt, ptr};
4
5use crate::{
6 translate::*,
7 value::{FromValue, ValueTypeChecker},
8 HasParamSpec, ParamSpecEnum, ParamSpecFlags, StaticType, Type, Value,
9};
10
11#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
12pub enum UserDirectory {
13 #[doc(alias = "G_USER_DIRECTORY_DESKTOP")]
14 Desktop,
15 #[doc(alias = "G_USER_DIRECTORY_DOCUMENTS")]
16 Documents,
17 #[doc(alias = "G_USER_DIRECTORY_DOWNLOAD")]
18 Downloads,
19 #[doc(alias = "G_USER_DIRECTORY_MUSIC")]
20 Music,
21 #[doc(alias = "G_USER_DIRECTORY_PICTURES")]
22 Pictures,
23 #[doc(alias = "G_USER_DIRECTORY_PUBLIC_SHARE")]
24 PublicShare,
25 #[doc(alias = "G_USER_DIRECTORY_TEMPLATES")]
26 Templates,
27 #[doc(alias = "G_USER_DIRECTORY_VIDEOS")]
28 Videos,
29}
30
31#[doc(hidden)]
32impl IntoGlib for UserDirectory {
33 type GlibType = ffi::GUserDirectory;
34
35 #[inline]
36 fn into_glib(self) -> ffi::GUserDirectory {
37 match self {
38 Self::Desktop => ffi::G_USER_DIRECTORY_DESKTOP,
39 Self::Documents => ffi::G_USER_DIRECTORY_DOCUMENTS,
40 Self::Downloads => ffi::G_USER_DIRECTORY_DOWNLOAD,
41 Self::Music => ffi::G_USER_DIRECTORY_MUSIC,
42 Self::Pictures => ffi::G_USER_DIRECTORY_PICTURES,
43 Self::PublicShare => ffi::G_USER_DIRECTORY_PUBLIC_SHARE,
44 Self::Templates => ffi::G_USER_DIRECTORY_TEMPLATES,
45 Self::Videos => ffi::G_USER_DIRECTORY_VIDEOS,
46 }
47 }
48}
49
50// rustdoc-stripper-ignore-next
51/// Representation of an `enum` for dynamically, at runtime, querying the values of the enum and
52/// using them.
53#[doc(alias = "GEnumClass")]
54#[repr(transparent)]
55pub struct EnumClass(ptr::NonNull<gobject_ffi::GEnumClass>);
56
57unsafe impl Send for EnumClass {}
58unsafe impl Sync for EnumClass {}
59
60impl fmt::Debug for EnumClass {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 f&mut DebugStruct<'_, '_>.debug_struct("EnumClass")
63 .field("type", &self.type_())
64 .field(name:"values", &self.values())
65 .finish()
66 }
67}
68
69impl EnumClass {
70 // rustdoc-stripper-ignore-next
71 /// Create a new `EnumClass` from a static type `T`.
72 ///
73 /// Panics if `T` is not representing an enum.
74 pub fn new<T: StaticType + HasParamSpec<ParamSpec = ParamSpecEnum>>() -> Self {
75 Self::with_type(T::static_type()).expect("invalid enum class")
76 }
77 // rustdoc-stripper-ignore-next
78 /// Create a new `EnumClass` from a `Type`.
79 ///
80 /// Returns `None` if `type_` is not representing an enum.
81 pub fn with_type(type_: Type) -> Option<Self> {
82 unsafe {
83 let is_enum: bool = from_glib(gobject_ffi::g_type_is_a(
84 type_.into_glib(),
85 gobject_ffi::G_TYPE_ENUM,
86 ));
87 if !is_enum {
88 return None;
89 }
90
91 Some(EnumClass(
92 ptr::NonNull::new(gobject_ffi::g_type_class_ref(type_.into_glib()) as *mut _)
93 .unwrap(),
94 ))
95 }
96 }
97
98 // rustdoc-stripper-ignore-next
99 /// `Type` of the enum.
100 pub fn type_(&self) -> Type {
101 unsafe { from_glib(self.0.as_ref().g_type_class.g_type) }
102 }
103
104 // rustdoc-stripper-ignore-next
105 /// Gets `EnumValue` by integer `value`, if existing.
106 ///
107 /// Returns `None` if the enum does not contain any value
108 /// with `value`.
109 #[doc(alias = "g_enum_get_value")]
110 #[doc(alias = "get_value")]
111 pub fn value(&self, value: i32) -> Option<&EnumValue> {
112 unsafe {
113 let v = gobject_ffi::g_enum_get_value(self.0.as_ptr(), value);
114 if v.is_null() {
115 None
116 } else {
117 Some(&*(v as *const EnumValue))
118 }
119 }
120 }
121
122 // rustdoc-stripper-ignore-next
123 /// Gets `EnumValue` by string name `name`, if existing.
124 ///
125 /// Returns `None` if the enum does not contain any value
126 /// with name `name`.
127 #[doc(alias = "g_enum_get_value_by_name")]
128 #[doc(alias = "get_value_by_name")]
129 pub fn value_by_name(&self, name: &str) -> Option<&EnumValue> {
130 unsafe {
131 let v = gobject_ffi::g_enum_get_value_by_name(self.0.as_ptr(), name.to_glib_none().0);
132 if v.is_null() {
133 None
134 } else {
135 Some(&*(v as *const EnumValue))
136 }
137 }
138 }
139
140 // rustdoc-stripper-ignore-next
141 /// Gets `EnumValue` by string nick `nick`, if existing.
142 ///
143 /// Returns `None` if the enum does not contain any value
144 /// with nick `nick`.
145 #[doc(alias = "g_enum_get_value_by_nick")]
146 #[doc(alias = "get_value_by_nick")]
147 pub fn value_by_nick(&self, nick: &str) -> Option<&EnumValue> {
148 unsafe {
149 let v = gobject_ffi::g_enum_get_value_by_nick(self.0.as_ptr(), nick.to_glib_none().0);
150 if v.is_null() {
151 None
152 } else {
153 Some(&*(v as *const EnumValue))
154 }
155 }
156 }
157
158 // rustdoc-stripper-ignore-next
159 /// Gets all `EnumValue` of this `EnumClass`.
160 #[doc(alias = "get_values")]
161 pub fn values(&self) -> &[EnumValue] {
162 unsafe {
163 if self.0.as_ref().n_values == 0 {
164 return &[];
165 }
166 std::slice::from_raw_parts(
167 self.0.as_ref().values as *const EnumValue,
168 self.0.as_ref().n_values as usize,
169 )
170 }
171 }
172
173 // rustdoc-stripper-ignore-next
174 /// Converts integer `value` to a `Value`, if part of the enum.
175 pub fn to_value(&self, value: i32) -> Option<Value> {
176 self.value(value).map(|v| v.to_value(self))
177 }
178
179 // rustdoc-stripper-ignore-next
180 /// Converts string name `name` to a `Value`, if part of the enum.
181 pub fn to_value_by_name(&self, name: &str) -> Option<Value> {
182 self.value_by_name(name).map(|v| v.to_value(self))
183 }
184
185 // rustdoc-stripper-ignore-next
186 /// Converts string nick `nick` to a `Value`, if part of the enum.
187 pub fn to_value_by_nick(&self, nick: &str) -> Option<Value> {
188 self.value_by_nick(nick).map(|v| v.to_value(self))
189 }
190}
191
192impl Drop for EnumClass {
193 #[inline]
194 fn drop(&mut self) {
195 unsafe {
196 gobject_ffi::g_type_class_unref(self.0.as_ptr() as *mut _);
197 }
198 }
199}
200
201impl Clone for EnumClass {
202 #[inline]
203 fn clone(&self) -> Self {
204 unsafe {
205 Self(ptr::NonNull::new(ptr:gobject_ffi::g_type_class_ref(self.type_().into_glib()) as *mut _).unwrap())
206 }
207 }
208}
209
210// rustdoc-stripper-ignore-next
211/// Representation of a single enum value of an `EnumClass`.
212#[doc(alias = "GEnumValue")]
213#[repr(transparent)]
214pub struct EnumValue(gobject_ffi::GEnumValue);
215
216unsafe impl Send for EnumValue {}
217unsafe impl Sync for EnumValue {}
218
219impl fmt::Debug for EnumValue {
220 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
221 f&mut DebugStruct<'_, '_>.debug_struct("EnumValue")
222 .field("value", &self.value())
223 .field("name", &self.name())
224 .field(name:"nick", &self.nick())
225 .finish()
226 }
227}
228
229impl EnumValue {
230 // rustdoc-stripper-ignore-next
231 /// Get integer value corresponding to the value.
232 #[doc(alias = "get_value")]
233 pub fn value(&self) -> i32 {
234 self.0.value
235 }
236
237 // rustdoc-stripper-ignore-next
238 /// Get name corresponding to the value.
239 #[doc(alias = "get_name")]
240 pub fn name(&self) -> &str {
241 unsafe { CStr::from_ptr(self.0.value_name).to_str().unwrap() }
242 }
243
244 // rustdoc-stripper-ignore-next
245 /// Get nick corresponding to the value.
246 #[doc(alias = "get_nick")]
247 pub fn nick(&self) -> &str {
248 unsafe { CStr::from_ptr(self.0.value_nick).to_str().unwrap() }
249 }
250
251 // rustdoc-stripper-ignore-next
252 /// Convert enum value to a `Value`.
253 pub fn to_value(&self, enum_: &EnumClass) -> Value {
254 unsafe {
255 let mut v = Value::from_type_unchecked(enum_.type_());
256 gobject_ffi::g_value_set_enum(v.to_glib_none_mut().0, self.0.value);
257 v
258 }
259 }
260
261 // rustdoc-stripper-ignore-next
262 /// Convert enum value from a `Value`.
263 pub fn from_value(value: &Value) -> Option<(EnumClass, &EnumValue)> {
264 unsafe {
265 let enum_class = EnumClass::with_type(value.type_())?;
266 let v = enum_class.value(gobject_ffi::g_value_get_enum(value.to_glib_none().0))?;
267 let v = &*(v as *const EnumValue);
268 Some((enum_class, v))
269 }
270 }
271}
272
273impl PartialEq for EnumValue {
274 fn eq(&self, other: &Self) -> bool {
275 self.value().eq(&other.value())
276 }
277}
278
279impl Eq for EnumValue {}
280
281impl PartialOrd for EnumValue {
282 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
283 Some(self.cmp(other))
284 }
285}
286
287impl Ord for EnumValue {
288 fn cmp(&self, other: &Self) -> cmp::Ordering {
289 self.value().cmp(&other.value())
290 }
291}
292
293unsafe impl<'a, 'b> FromValue<'a> for &'b EnumValue {
294 type Checker = EnumTypeChecker;
295
296 unsafe fn from_value(value: &'a Value) -> Self {
297 let (_, v: &EnumValue) = EnumValue::from_value(value).unwrap();
298 // SAFETY: The enum class and its values live forever
299 std::mem::transmute(src:v)
300 }
301}
302
303pub struct EnumTypeChecker();
304unsafe impl ValueTypeChecker for EnumTypeChecker {
305 type Error = InvalidEnumError;
306
307 fn check(value: &Value) -> Result<(), Self::Error> {
308 let t: Type = value.type_();
309 if t.is_a(Type::ENUM) {
310 Ok(())
311 } else {
312 Err(InvalidEnumError)
313 }
314 }
315}
316
317// rustdoc-stripper-ignore-next
318/// An error returned from the [`get`](struct.Value.html#method.get) function
319/// on a [`Value`](struct.Value.html) for enum types.
320#[derive(Clone, PartialEq, Eq, Debug)]
321pub struct InvalidEnumError;
322
323impl fmt::Display for InvalidEnumError {
324 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
325 write!(f, "Value is not an enum")
326 }
327}
328
329impl std::error::Error for InvalidEnumError {}
330
331// rustdoc-stripper-ignore-next
332/// Representation of a `flags` for dynamically, at runtime, querying the values of the enum and
333/// using them
334#[doc(alias = "GFlagsClass")]
335#[repr(transparent)]
336pub struct FlagsClass(ptr::NonNull<gobject_ffi::GFlagsClass>);
337
338unsafe impl Send for FlagsClass {}
339unsafe impl Sync for FlagsClass {}
340
341impl fmt::Debug for FlagsClass {
342 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
343 f&mut DebugStruct<'_, '_>.debug_struct("FlagsClass")
344 .field("type", &self.type_())
345 .field(name:"values", &self.values())
346 .finish()
347 }
348}
349
350impl FlagsClass {
351 // rustdoc-stripper-ignore-next
352 /// Create a new `FlagsClass` from a static type `T`.
353 ///
354 /// Panics if `T` is not representing an flags type.
355 pub fn new<T: StaticType + HasParamSpec<ParamSpec = ParamSpecFlags>>() -> Self {
356 Self::with_type(T::static_type()).expect("invalid flags class")
357 }
358 // rustdoc-stripper-ignore-next
359 /// Create a new `FlagsClass` from a `Type`
360 ///
361 /// Returns `None` if `type_` is not representing a flags type.
362 pub fn with_type(type_: Type) -> Option<Self> {
363 unsafe {
364 let is_flags: bool = from_glib(gobject_ffi::g_type_is_a(
365 type_.into_glib(),
366 gobject_ffi::G_TYPE_FLAGS,
367 ));
368 if !is_flags {
369 return None;
370 }
371
372 Some(FlagsClass(
373 ptr::NonNull::new(gobject_ffi::g_type_class_ref(type_.into_glib()) as *mut _)
374 .unwrap(),
375 ))
376 }
377 }
378
379 // rustdoc-stripper-ignore-next
380 /// `Type` of the flags.
381 pub fn type_(&self) -> Type {
382 unsafe { from_glib(self.0.as_ref().g_type_class.g_type) }
383 }
384
385 // rustdoc-stripper-ignore-next
386 /// Gets `FlagsValue` by integer `value`, if existing.
387 ///
388 /// Returns `None` if the flags do not contain any value
389 /// with `value`.
390 #[doc(alias = "g_flags_get_first_value")]
391 #[doc(alias = "get_value")]
392 pub fn value(&self, value: u32) -> Option<&FlagsValue> {
393 unsafe {
394 let v = gobject_ffi::g_flags_get_first_value(self.0.as_ptr(), value);
395 if v.is_null() {
396 None
397 } else {
398 Some(&*(v as *const FlagsValue))
399 }
400 }
401 }
402
403 // rustdoc-stripper-ignore-next
404 /// Gets `FlagsValue` by string name `name`, if existing.
405 ///
406 /// Returns `None` if the flags do not contain any value
407 /// with name `name`.
408 #[doc(alias = "g_flags_get_value_by_name")]
409 #[doc(alias = "get_value_by_name")]
410 pub fn value_by_name(&self, name: &str) -> Option<&FlagsValue> {
411 unsafe {
412 let v = gobject_ffi::g_flags_get_value_by_name(self.0.as_ptr(), name.to_glib_none().0);
413 if v.is_null() {
414 None
415 } else {
416 Some(&*(v as *const FlagsValue))
417 }
418 }
419 }
420
421 // rustdoc-stripper-ignore-next
422 /// Gets `FlagsValue` by string nick `nick`, if existing.
423 ///
424 /// Returns `None` if the flags do not contain any value
425 /// with nick `nick`.
426 #[doc(alias = "g_flags_get_value_by_nick")]
427 #[doc(alias = "get_value_by_nick")]
428 pub fn value_by_nick(&self, nick: &str) -> Option<&FlagsValue> {
429 unsafe {
430 let v = gobject_ffi::g_flags_get_value_by_nick(self.0.as_ptr(), nick.to_glib_none().0);
431 if v.is_null() {
432 None
433 } else {
434 Some(&*(v as *const FlagsValue))
435 }
436 }
437 }
438
439 // rustdoc-stripper-ignore-next
440 /// Gets all `FlagsValue` of this `FlagsClass`.
441 #[doc(alias = "get_values")]
442 pub fn values(&self) -> &[FlagsValue] {
443 unsafe {
444 if self.0.as_ref().n_values == 0 {
445 return &[];
446 }
447 std::slice::from_raw_parts(
448 self.0.as_ref().values as *const FlagsValue,
449 self.0.as_ref().n_values as usize,
450 )
451 }
452 }
453
454 // rustdoc-stripper-ignore-next
455 /// Converts integer `value` to a `Value`, if part of the flags.
456 pub fn to_value(&self, value: u32) -> Option<Value> {
457 self.value(value).map(|v| v.to_value(self))
458 }
459
460 // rustdoc-stripper-ignore-next
461 /// Converts string name `name` to a `Value`, if part of the flags.
462 pub fn to_value_by_name(&self, name: &str) -> Option<Value> {
463 self.value_by_name(name).map(|v| v.to_value(self))
464 }
465
466 // rustdoc-stripper-ignore-next
467 /// Converts string nick `nick` to a `Value`, if part of the flags.
468 pub fn to_value_by_nick(&self, nick: &str) -> Option<Value> {
469 self.value_by_nick(nick).map(|v| v.to_value(self))
470 }
471
472 // rustdoc-stripper-ignore-next
473 /// Checks if the flags corresponding to integer `f` is set in `value`.
474 pub fn is_set(&self, value: &Value, f: u32) -> bool {
475 unsafe {
476 if self.type_() != value.type_() {
477 return false;
478 }
479
480 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
481 flags & f != 0
482 }
483 }
484
485 // rustdoc-stripper-ignore-next
486 /// Checks if the flags corresponding to string name `name` is set in `value`.
487 pub fn is_set_by_name(&self, value: &Value, name: &str) -> bool {
488 unsafe {
489 if self.type_() != value.type_() {
490 return false;
491 }
492
493 if let Some(f) = self.value_by_name(name) {
494 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
495 flags & f.value() != 0
496 } else {
497 false
498 }
499 }
500 }
501
502 // rustdoc-stripper-ignore-next
503 /// Checks if the flags corresponding to string nick `nick` is set in `value`.
504 pub fn is_set_by_nick(&self, value: &Value, nick: &str) -> bool {
505 unsafe {
506 if self.type_() != value.type_() {
507 return false;
508 }
509
510 if let Some(f) = self.value_by_nick(nick) {
511 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
512 flags & f.value() != 0
513 } else {
514 false
515 }
516 }
517 }
518
519 // rustdoc-stripper-ignore-next
520 /// Set flags value corresponding to integer `f` in `value`, if part of that flags. If the
521 /// flag is already set, it will succeed without doing any changes.
522 ///
523 /// Returns `Ok(value)` with the flag set if successful, or `Err(value)` with the original
524 /// value otherwise.
525 #[doc(alias = "g_value_set_flags")]
526 pub fn set(&self, mut value: Value, f: u32) -> Result<Value, Value> {
527 unsafe {
528 if self.type_() != value.type_() {
529 return Err(value);
530 }
531
532 if let Some(f) = self.value(f) {
533 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
534 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value());
535 Ok(value)
536 } else {
537 Err(value)
538 }
539 }
540 }
541
542 // rustdoc-stripper-ignore-next
543 /// Set flags value corresponding to string name `name` in `value`, if part of that flags.
544 /// If the flag is already set, it will succeed without doing any changes.
545 ///
546 /// Returns `Ok(value)` with the flag set if successful, or `Err(value)` with the original
547 /// value otherwise.
548 pub fn set_by_name(&self, mut value: Value, name: &str) -> Result<Value, Value> {
549 unsafe {
550 if self.type_() != value.type_() {
551 return Err(value);
552 }
553
554 if let Some(f) = self.value_by_name(name) {
555 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
556 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value());
557 Ok(value)
558 } else {
559 Err(value)
560 }
561 }
562 }
563
564 // rustdoc-stripper-ignore-next
565 /// Set flags value corresponding to string nick `nick` in `value`, if part of that flags.
566 /// If the flag is already set, it will succeed without doing any changes.
567 ///
568 /// Returns `Ok(value)` with the flag set if successful, or `Err(value)` with the original
569 /// value otherwise.
570 pub fn set_by_nick(&self, mut value: Value, nick: &str) -> Result<Value, Value> {
571 unsafe {
572 if self.type_() != value.type_() {
573 return Err(value);
574 }
575
576 if let Some(f) = self.value_by_nick(nick) {
577 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
578 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value());
579 Ok(value)
580 } else {
581 Err(value)
582 }
583 }
584 }
585
586 // rustdoc-stripper-ignore-next
587 /// Unset flags value corresponding to integer `f` in `value`, if part of that flags.
588 /// If the flag is already unset, it will succeed without doing any changes.
589 ///
590 /// Returns `Ok(value)` with the flag unset if successful, or `Err(value)` with the original
591 /// value otherwise.
592 pub fn unset(&self, mut value: Value, f: u32) -> Result<Value, Value> {
593 unsafe {
594 if self.type_() != value.type_() {
595 return Err(value);
596 }
597
598 if let Some(f) = self.value(f) {
599 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
600 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value());
601 Ok(value)
602 } else {
603 Err(value)
604 }
605 }
606 }
607
608 // rustdoc-stripper-ignore-next
609 /// Unset flags value corresponding to string name `name` in `value`, if part of that flags.
610 /// If the flag is already unset, it will succeed without doing any changes.
611 ///
612 /// Returns `Ok(value)` with the flag unset if successful, or `Err(value)` with the original
613 /// value otherwise.
614 pub fn unset_by_name(&self, mut value: Value, name: &str) -> Result<Value, Value> {
615 unsafe {
616 if self.type_() != value.type_() {
617 return Err(value);
618 }
619
620 if let Some(f) = self.value_by_name(name) {
621 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
622 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value());
623 Ok(value)
624 } else {
625 Err(value)
626 }
627 }
628 }
629
630 // rustdoc-stripper-ignore-next
631 /// Unset flags value corresponding to string nick `nick` in `value`, if part of that flags.
632 /// If the flag is already unset, it will succeed without doing any changes.
633 ///
634 /// Returns `Ok(value)` with the flag unset if successful, or `Err(value)` with the original
635 /// value otherwise.
636 pub fn unset_by_nick(&self, mut value: Value, nick: &str) -> Result<Value, Value> {
637 unsafe {
638 if self.type_() != value.type_() {
639 return Err(value);
640 }
641
642 if let Some(f) = self.value_by_nick(nick) {
643 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
644 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value());
645 Ok(value)
646 } else {
647 Err(value)
648 }
649 }
650 }
651
652 // rustdoc-stripper-ignore-next
653 /// Converts an integer `value` to a string of nicks separated by `|`.
654 pub fn to_nick_string(&self, mut value: u32) -> String {
655 let mut s = String::new();
656 for val in self.values() {
657 let v = val.value();
658 if v != 0 && (value & v) == v {
659 value &= !v;
660 if !s.is_empty() {
661 s.push('|');
662 }
663 s.push_str(val.nick());
664 }
665 }
666 s
667 }
668
669 // rustdoc-stripper-ignore-next
670 /// Converts a string of nicks `s` separated by `|` to an integer value.
671 pub fn from_nick_string(&self, s: &str) -> Result<u32, ParseFlagsError> {
672 s.split('|').try_fold(0u32, |acc, flag| {
673 self.value_by_nick(flag.trim())
674 .map(|v| acc + v.value())
675 .ok_or_else(|| ParseFlagsError(flag.to_owned()))
676 })
677 }
678
679 // rustdoc-stripper-ignore-next
680 /// Returns a new `FlagsBuilder` for conveniently setting/unsetting flags
681 /// and building a `Value`.
682 pub fn builder(&self) -> FlagsBuilder {
683 FlagsBuilder::new(self)
684 }
685
686 // rustdoc-stripper-ignore-next
687 /// Returns a new `FlagsBuilder` for conveniently setting/unsetting flags
688 /// and building a `Value`. The `Value` is initialized with `value`.
689 pub fn builder_with_value(&self, value: Value) -> Option<FlagsBuilder> {
690 if self.type_() != value.type_() {
691 return None;
692 }
693
694 Some(FlagsBuilder::with_value(self, value))
695 }
696}
697
698impl Drop for FlagsClass {
699 #[inline]
700 fn drop(&mut self) {
701 unsafe {
702 gobject_ffi::g_type_class_unref(self.0.as_ptr() as *mut _);
703 }
704 }
705}
706
707impl Clone for FlagsClass {
708 #[inline]
709 fn clone(&self) -> Self {
710 unsafe {
711 Self(ptr::NonNull::new(ptr:gobject_ffi::g_type_class_ref(self.type_().into_glib()) as *mut _).unwrap())
712 }
713 }
714}
715
716#[derive(Debug)]
717pub struct ParseFlagsError(String);
718
719impl std::error::Error for ParseFlagsError {}
720
721impl fmt::Display for ParseFlagsError {
722 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
723 write!(f, "Unknown flag: '{}'", self.0)
724 }
725}
726
727impl ParseFlagsError {
728 pub fn flag(&self) -> &str {
729 &self.0
730 }
731}
732
733// rustdoc-stripper-ignore-next
734/// Representation of a single flags value of a `FlagsClass`.
735#[doc(alias = "GFlagsValue")]
736#[repr(transparent)]
737pub struct FlagsValue(gobject_ffi::GFlagsValue);
738
739unsafe impl Send for FlagsValue {}
740unsafe impl Sync for FlagsValue {}
741
742impl fmt::Debug for FlagsValue {
743 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
744 f&mut DebugStruct<'_, '_>.debug_struct("FlagsValue")
745 .field("value", &self.value())
746 .field("name", &self.name())
747 .field(name:"nick", &self.nick())
748 .finish()
749 }
750}
751
752impl FlagsValue {
753 // rustdoc-stripper-ignore-next
754 /// Get integer value corresponding to the value.
755 #[doc(alias = "get_value")]
756 pub fn value(&self) -> u32 {
757 self.0.value
758 }
759
760 // rustdoc-stripper-ignore-next
761 /// Get name corresponding to the value.
762 #[doc(alias = "get_name")]
763 pub fn name(&self) -> &str {
764 unsafe { CStr::from_ptr(self.0.value_name).to_str().unwrap() }
765 }
766
767 // rustdoc-stripper-ignore-next
768 /// Get nick corresponding to the value.
769 #[doc(alias = "get_nick")]
770 pub fn nick(&self) -> &str {
771 unsafe { CStr::from_ptr(self.0.value_nick).to_str().unwrap() }
772 }
773
774 // rustdoc-stripper-ignore-next
775 /// Convert flags value to a `Value`.
776 pub fn to_value(&self, flags: &FlagsClass) -> Value {
777 unsafe {
778 let mut v = Value::from_type_unchecked(flags.type_());
779 gobject_ffi::g_value_set_flags(v.to_glib_none_mut().0, self.0.value);
780 v
781 }
782 }
783
784 // rustdoc-stripper-ignore-next
785 /// Convert flags values from a `Value`. This returns all flags that are set.
786 pub fn from_value(value: &Value) -> Option<(FlagsClass, Vec<&FlagsValue>)> {
787 unsafe {
788 let flags_class = FlagsClass::with_type(value.type_())?;
789 let mut res = Vec::new();
790 let f = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
791 for v in flags_class.values() {
792 if v.value() & f != 0 {
793 res.push(&*(v as *const FlagsValue));
794 }
795 }
796 Some((flags_class, res))
797 }
798 }
799}
800
801impl PartialEq for FlagsValue {
802 fn eq(&self, other: &Self) -> bool {
803 self.value().eq(&other.value())
804 }
805}
806
807impl Eq for FlagsValue {}
808
809// rustdoc-stripper-ignore-next
810/// Builder for conveniently setting/unsetting flags and returning a `Value`.
811///
812/// Example for getting a flags property, unsetting some flags and setting the updated flags on the
813/// object again:
814///
815/// ```ignore
816/// let flags = obj.property("flags").unwrap();
817/// let flags_class = FlagsClass::new(flags.type_()).unwrap();
818/// let flags = flags_class.builder_with_value(flags).unwrap()
819/// .unset_by_nick("some-flag")
820/// .unset_by_nick("some-other-flag")
821/// .build()
822/// .unwrap();
823/// obj.set_property("flags", &flags).unwrap();
824/// ```
825///
826/// If setting/unsetting any value fails, `build()` returns `None`.
827#[must_use = "The builder must be built to be used"]
828pub struct FlagsBuilder<'a>(&'a FlagsClass, Option<Value>);
829impl<'a> FlagsBuilder<'a> {
830 fn new(flags_class: &FlagsClass) -> FlagsBuilder {
831 let value = unsafe { Value::from_type_unchecked(flags_class.type_()) };
832 FlagsBuilder(flags_class, Some(value))
833 }
834
835 fn with_value(flags_class: &FlagsClass, value: Value) -> FlagsBuilder {
836 FlagsBuilder(flags_class, Some(value))
837 }
838
839 // rustdoc-stripper-ignore-next
840 /// Set flags corresponding to integer value `f`.
841 pub fn set(mut self, f: u32) -> Self {
842 if let Some(value) = self.1.take() {
843 self.1 = self.0.set(value, f).ok();
844 }
845
846 self
847 }
848
849 // rustdoc-stripper-ignore-next
850 /// Set flags corresponding to string name `name`.
851 pub fn set_by_name(mut self, name: &str) -> Self {
852 if let Some(value) = self.1.take() {
853 self.1 = self.0.set_by_name(value, name).ok();
854 }
855
856 self
857 }
858
859 // rustdoc-stripper-ignore-next
860 /// Set flags corresponding to string nick `nick`.
861 pub fn set_by_nick(mut self, nick: &str) -> Self {
862 if let Some(value) = self.1.take() {
863 self.1 = self.0.set_by_nick(value, nick).ok();
864 }
865
866 self
867 }
868
869 // rustdoc-stripper-ignore-next
870 /// Unsets flags corresponding to integer value `f`.
871 pub fn unset(mut self, f: u32) -> Self {
872 if let Some(value) = self.1.take() {
873 self.1 = self.0.unset(value, f).ok();
874 }
875
876 self
877 }
878
879 // rustdoc-stripper-ignore-next
880 /// Unset flags corresponding to string name `name`.
881 pub fn unset_by_name(mut self, name: &str) -> Self {
882 if let Some(value) = self.1.take() {
883 self.1 = self.0.unset_by_name(value, name).ok();
884 }
885
886 self
887 }
888
889 // rustdoc-stripper-ignore-next
890 /// Unset flags corresponding to string nick `nick`.
891 pub fn unset_by_nick(mut self, nick: &str) -> Self {
892 if let Some(value) = self.1.take() {
893 self.1 = self.0.unset_by_nick(value, nick).ok();
894 }
895
896 self
897 }
898
899 // rustdoc-stripper-ignore-next
900 /// Converts to the final `Value`, unless any previous setting/unsetting of flags failed.
901 #[must_use = "Value returned from the builder should probably be used"]
902 pub fn build(self) -> Option<Value> {
903 self.1
904 }
905}
906
907unsafe impl<'a, 'b> FromValue<'a> for Vec<&'b FlagsValue> {
908 type Checker = FlagsTypeChecker;
909
910 unsafe fn from_value(value: &'a Value) -> Self {
911 let (_, v: Vec<&FlagsValue>) = FlagsValue::from_value(value).unwrap();
912 // SAFETY: The enum class and its values live forever
913 std::mem::transmute(src:v)
914 }
915}
916
917pub struct FlagsTypeChecker();
918unsafe impl ValueTypeChecker for FlagsTypeChecker {
919 type Error = InvalidFlagsError;
920
921 fn check(value: &Value) -> Result<(), Self::Error> {
922 let t: Type = value.type_();
923 if t.is_a(Type::FLAGS) {
924 Ok(())
925 } else {
926 Err(InvalidFlagsError)
927 }
928 }
929}
930
931// rustdoc-stripper-ignore-next
932/// An error returned from the [`get`](struct.Value.html#method.get) function
933/// on a [`Value`](struct.Value.html) for flags types.
934#[derive(Clone, PartialEq, Eq, Debug)]
935pub struct InvalidFlagsError;
936
937impl fmt::Display for InvalidFlagsError {
938 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
939 write!(f, "Value is not a flags")
940 }
941}
942
943impl std::error::Error for InvalidFlagsError {}
944
945#[cfg(test)]
946mod tests {
947 use super::*;
948
949 #[test]
950 fn test_flags() {
951 let flags = FlagsClass::new::<crate::BindingFlags>();
952 let values = flags.values();
953 let def1 = values
954 .iter()
955 .find(|v| v.name() == "G_BINDING_DEFAULT")
956 .unwrap();
957 let def2 = flags.value_by_name("G_BINDING_DEFAULT").unwrap();
958 assert!(ptr::eq(def1, def2));
959
960 let value = flags.to_value(0).unwrap();
961 let values = value.get::<Vec<&FlagsValue>>().unwrap();
962 assert_eq!(values.len(), 0);
963
964 assert_eq!(def1.value(), crate::BindingFlags::DEFAULT.bits());
965 }
966}
967