1use std::{cmp, ffi::CStr, fmt, ops::Deref, ptr};
4
5use crate::{
6 ffi, gobject_ffi, prelude::*, translate::*, ParamSpecEnum, ParamSpecFlags, Type, TypeInfo,
7 Value,
8};
9
10#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
18pub enum UserDirectory {
19 #[doc(alias = "G_USER_DIRECTORY_DESKTOP")]
20 Desktop,
21 #[doc(alias = "G_USER_DIRECTORY_DOCUMENTS")]
22 Documents,
23 #[doc(alias = "G_USER_DIRECTORY_DOWNLOAD")]
24 Downloads,
25 #[doc(alias = "G_USER_DIRECTORY_MUSIC")]
26 Music,
27 #[doc(alias = "G_USER_DIRECTORY_PICTURES")]
28 Pictures,
29 #[doc(alias = "G_USER_DIRECTORY_PUBLIC_SHARE")]
30 PublicShare,
31 #[doc(alias = "G_USER_DIRECTORY_TEMPLATES")]
32 Templates,
33 #[doc(alias = "G_USER_DIRECTORY_VIDEOS")]
34 Videos,
35}
36
37#[doc(hidden)]
38impl IntoGlib for UserDirectory {
39 type GlibType = ffi::GUserDirectory;
40
41 #[inline]
42 fn into_glib(self) -> ffi::GUserDirectory {
43 match self {
44 Self::Desktop => ffi::G_USER_DIRECTORY_DESKTOP,
45 Self::Documents => ffi::G_USER_DIRECTORY_DOCUMENTS,
46 Self::Downloads => ffi::G_USER_DIRECTORY_DOWNLOAD,
47 Self::Music => ffi::G_USER_DIRECTORY_MUSIC,
48 Self::Pictures => ffi::G_USER_DIRECTORY_PICTURES,
49 Self::PublicShare => ffi::G_USER_DIRECTORY_PUBLIC_SHARE,
50 Self::Templates => ffi::G_USER_DIRECTORY_TEMPLATES,
51 Self::Videos => ffi::G_USER_DIRECTORY_VIDEOS,
52 }
53 }
54}
55
56#[doc(alias = "GEnumClass")]
60#[repr(transparent)]
61pub struct EnumClass(ptr::NonNull<gobject_ffi::GEnumClass>);
62
63unsafe impl Send for EnumClass {}
64unsafe impl Sync for EnumClass {}
65
66impl fmt::Debug for EnumClass {
67 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68 f.debug_struct("EnumClass")
69 .field("type", &self.type_())
70 .field("values", &self.values())
71 .finish()
72 }
73}
74
75impl EnumClass {
76 pub fn new<T: StaticType + HasParamSpec<ParamSpec = ParamSpecEnum>>() -> Self {
81 Self::with_type(T::static_type()).expect("invalid enum class")
82 }
83 pub fn with_type(type_: Type) -> Option<Self> {
88 unsafe {
89 let is_enum: bool = from_glib(gobject_ffi::g_type_is_a(
90 type_.into_glib(),
91 gobject_ffi::G_TYPE_ENUM,
92 ));
93 if !is_enum {
94 return None;
95 }
96
97 Some(EnumClass(
98 ptr::NonNull::new(gobject_ffi::g_type_class_ref(type_.into_glib()) as *mut _)
99 .unwrap(),
100 ))
101 }
102 }
103
104 pub fn type_(&self) -> Type {
107 unsafe { from_glib(self.0.as_ref().g_type_class.g_type) }
108 }
109
110 #[doc(alias = "g_enum_get_value")]
116 #[doc(alias = "get_value")]
117 pub fn value(&self, value: i32) -> Option<&EnumValue> {
118 unsafe {
119 let v = gobject_ffi::g_enum_get_value(self.0.as_ptr(), value);
120 if v.is_null() {
121 None
122 } else {
123 Some(&*(v as *const EnumValue))
124 }
125 }
126 }
127
128 #[doc(alias = "g_enum_get_value_by_name")]
134 #[doc(alias = "get_value_by_name")]
135 pub fn value_by_name(&self, name: &str) -> Option<&EnumValue> {
136 unsafe {
137 let v = gobject_ffi::g_enum_get_value_by_name(self.0.as_ptr(), name.to_glib_none().0);
138 if v.is_null() {
139 None
140 } else {
141 Some(&*(v as *const EnumValue))
142 }
143 }
144 }
145
146 #[doc(alias = "g_enum_get_value_by_nick")]
152 #[doc(alias = "get_value_by_nick")]
153 pub fn value_by_nick(&self, nick: &str) -> Option<&EnumValue> {
154 unsafe {
155 let v = gobject_ffi::g_enum_get_value_by_nick(self.0.as_ptr(), nick.to_glib_none().0);
156 if v.is_null() {
157 None
158 } else {
159 Some(&*(v as *const EnumValue))
160 }
161 }
162 }
163
164 #[doc(alias = "get_values")]
167 pub fn values(&self) -> &[EnumValue] {
168 unsafe {
169 if self.0.as_ref().n_values == 0 {
170 return &[];
171 }
172 std::slice::from_raw_parts(
173 self.0.as_ref().values as *const EnumValue,
174 self.0.as_ref().n_values as usize,
175 )
176 }
177 }
178
179 pub fn to_value(&self, value: i32) -> Option<Value> {
182 self.value(value).map(|v| v.to_value(self))
183 }
184
185 pub fn to_value_by_name(&self, name: &str) -> Option<Value> {
188 self.value_by_name(name).map(|v| v.to_value(self))
189 }
190
191 pub fn to_value_by_nick(&self, nick: &str) -> Option<Value> {
194 self.value_by_nick(nick).map(|v| v.to_value(self))
195 }
196
197 #[doc(alias = "g_enum_complete_type_info")]
207 pub fn complete_type_info(
208 type_: Type,
209 const_static_values: &'static EnumValues,
210 ) -> Option<TypeInfo> {
211 unsafe {
212 let is_enum: bool = from_glib(gobject_ffi::g_type_is_a(
213 type_.into_glib(),
214 gobject_ffi::G_TYPE_ENUM,
215 ));
216 if !is_enum {
217 return None;
218 }
219
220 let info = TypeInfo::default();
221 gobject_ffi::g_enum_complete_type_info(
222 type_.into_glib(),
223 info.as_ptr(),
224 const_static_values.to_glib_none().0,
225 );
226 Some(info)
227 }
228 }
229}
230
231impl Drop for EnumClass {
232 #[inline]
233 fn drop(&mut self) {
234 unsafe {
235 gobject_ffi::g_type_class_unref(self.0.as_ptr() as *mut _);
236 }
237 }
238}
239
240impl Clone for EnumClass {
241 #[inline]
242 fn clone(&self) -> Self {
243 unsafe {
244 Self(ptr::NonNull::new(gobject_ffi::g_type_class_ref(self.type_().into_glib()) as *mut _).unwrap())
245 }
246 }
247}
248
249#[doc(alias = "GEnumValue")]
252#[derive(Copy, Clone)]
253#[repr(transparent)]
254pub struct EnumValue(gobject_ffi::GEnumValue);
255
256unsafe impl Send for EnumValue {}
257unsafe impl Sync for EnumValue {}
258
259impl fmt::Debug for EnumValue {
260 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
261 f.debug_struct("EnumValue")
262 .field("value", &self.value())
263 .field("name", &self.name())
264 .field("nick", &self.nick())
265 .finish()
266 }
267}
268
269impl EnumValue {
270 pub const unsafe fn unsafe_from(g_value: gobject_ffi::GEnumValue) -> Self {
276 Self(g_value)
277 }
278
279 #[doc(alias = "get_value")]
282 pub fn value(&self) -> i32 {
283 self.0.value
284 }
285
286 #[doc(alias = "get_name")]
289 pub fn name(&self) -> &str {
290 unsafe { CStr::from_ptr(self.0.value_name).to_str().unwrap() }
291 }
292
293 #[doc(alias = "get_nick")]
296 pub fn nick(&self) -> &str {
297 unsafe { CStr::from_ptr(self.0.value_nick).to_str().unwrap() }
298 }
299
300 pub fn to_value(&self, enum_: &EnumClass) -> Value {
303 unsafe {
304 let mut v = Value::from_type_unchecked(enum_.type_());
305 gobject_ffi::g_value_set_enum(v.to_glib_none_mut().0, self.0.value);
306 v
307 }
308 }
309
310 pub fn from_value(value: &Value) -> Option<(EnumClass, &EnumValue)> {
313 unsafe {
314 let enum_class = EnumClass::with_type(value.type_())?;
315 let v = enum_class.value(gobject_ffi::g_value_get_enum(value.to_glib_none().0))?;
316 let v = &*(v as *const EnumValue);
317 Some((enum_class, v))
318 }
319 }
320}
321
322impl PartialEq for EnumValue {
323 fn eq(&self, other: &Self) -> bool {
324 self.value().eq(&other.value())
325 }
326}
327
328impl Eq for EnumValue {}
329
330impl PartialOrd for EnumValue {
331 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
332 Some(self.cmp(other))
333 }
334}
335
336impl Ord for EnumValue {
337 fn cmp(&self, other: &Self) -> cmp::Ordering {
338 self.value().cmp(&other.value())
339 }
340}
341
342impl UnsafeFrom<gobject_ffi::GEnumValue> for EnumValue {
343 unsafe fn unsafe_from(g_value: gobject_ffi::GEnumValue) -> Self {
344 Self::unsafe_from(g_value)
345 }
346}
347
348unsafe impl<'a> crate::value::FromValue<'a> for &EnumValue {
349 type Checker = EnumTypeChecker;
350
351 unsafe fn from_value(value: &'a Value) -> Self {
352 let (_, v) = EnumValue::from_value(value).unwrap();
353 std::mem::transmute(v)
355 }
356}
357
358impl EnumerationValue<EnumValue> for EnumValue {
361 type GlibType = gobject_ffi::GEnumValue;
362 const ZERO: EnumValue = unsafe {
363 EnumValue::unsafe_from(gobject_ffi::GEnumValue {
364 value: 0,
365 value_name: ptr::null(),
366 value_nick: ptr::null(),
367 })
368 };
369}
370
371pub type EnumValuesStorage<const N: usize> = EnumerationValuesStorage<EnumValue, N>;
374
375pub type EnumValues = EnumerationValues<EnumValue>;
378
379pub struct EnumTypeChecker();
380unsafe impl crate::value::ValueTypeChecker for EnumTypeChecker {
381 type Error = InvalidEnumError;
382
383 fn check(value: &Value) -> Result<(), Self::Error> {
384 let t = value.type_();
385 if t.is_a(Type::ENUM) {
386 Ok(())
387 } else {
388 Err(InvalidEnumError)
389 }
390 }
391}
392
393#[derive(Clone, PartialEq, Eq, Debug)]
397pub struct InvalidEnumError;
398
399impl fmt::Display for InvalidEnumError {
400 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
401 write!(f, "Value is not an enum")
402 }
403}
404
405impl std::error::Error for InvalidEnumError {}
406
407#[doc(alias = "GFlagsClass")]
411#[repr(transparent)]
412pub struct FlagsClass(ptr::NonNull<gobject_ffi::GFlagsClass>);
413
414unsafe impl Send for FlagsClass {}
415unsafe impl Sync for FlagsClass {}
416
417impl fmt::Debug for FlagsClass {
418 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
419 f.debug_struct("FlagsClass")
420 .field("type", &self.type_())
421 .field("values", &self.values())
422 .finish()
423 }
424}
425
426impl FlagsClass {
427 pub fn new<T: StaticType + HasParamSpec<ParamSpec = ParamSpecFlags>>() -> Self {
432 Self::with_type(T::static_type()).expect("invalid flags class")
433 }
434 pub fn with_type(type_: Type) -> Option<Self> {
439 unsafe {
440 let is_flags: bool = from_glib(gobject_ffi::g_type_is_a(
441 type_.into_glib(),
442 gobject_ffi::G_TYPE_FLAGS,
443 ));
444 if !is_flags {
445 return None;
446 }
447
448 Some(FlagsClass(
449 ptr::NonNull::new(gobject_ffi::g_type_class_ref(type_.into_glib()) as *mut _)
450 .unwrap(),
451 ))
452 }
453 }
454
455 pub fn type_(&self) -> Type {
458 unsafe { from_glib(self.0.as_ref().g_type_class.g_type) }
459 }
460
461 #[doc(alias = "g_flags_get_first_value")]
467 #[doc(alias = "get_value")]
468 pub fn value(&self, value: u32) -> Option<&FlagsValue> {
469 unsafe {
470 let v = gobject_ffi::g_flags_get_first_value(self.0.as_ptr(), value);
471 if v.is_null() {
472 None
473 } else {
474 Some(&*(v as *const FlagsValue))
475 }
476 }
477 }
478
479 #[doc(alias = "g_flags_get_value_by_name")]
485 #[doc(alias = "get_value_by_name")]
486 pub fn value_by_name(&self, name: &str) -> Option<&FlagsValue> {
487 unsafe {
488 let v = gobject_ffi::g_flags_get_value_by_name(self.0.as_ptr(), name.to_glib_none().0);
489 if v.is_null() {
490 None
491 } else {
492 Some(&*(v as *const FlagsValue))
493 }
494 }
495 }
496
497 #[doc(alias = "g_flags_get_value_by_nick")]
503 #[doc(alias = "get_value_by_nick")]
504 pub fn value_by_nick(&self, nick: &str) -> Option<&FlagsValue> {
505 unsafe {
506 let v = gobject_ffi::g_flags_get_value_by_nick(self.0.as_ptr(), nick.to_glib_none().0);
507 if v.is_null() {
508 None
509 } else {
510 Some(&*(v as *const FlagsValue))
511 }
512 }
513 }
514
515 #[doc(alias = "get_values")]
518 pub fn values(&self) -> &[FlagsValue] {
519 unsafe {
520 if self.0.as_ref().n_values == 0 {
521 return &[];
522 }
523 std::slice::from_raw_parts(
524 self.0.as_ref().values as *const FlagsValue,
525 self.0.as_ref().n_values as usize,
526 )
527 }
528 }
529
530 pub fn to_value(&self, value: u32) -> Option<Value> {
533 self.value(value).map(|v| v.to_value(self))
534 }
535
536 pub fn to_value_by_name(&self, name: &str) -> Option<Value> {
539 self.value_by_name(name).map(|v| v.to_value(self))
540 }
541
542 pub fn to_value_by_nick(&self, nick: &str) -> Option<Value> {
545 self.value_by_nick(nick).map(|v| v.to_value(self))
546 }
547
548 pub fn is_set(&self, value: &Value, f: u32) -> bool {
551 unsafe {
552 if self.type_() != value.type_() {
553 return false;
554 }
555
556 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
557 flags & f != 0
558 }
559 }
560
561 pub fn is_set_by_name(&self, value: &Value, name: &str) -> bool {
564 unsafe {
565 if self.type_() != value.type_() {
566 return false;
567 }
568
569 if let Some(f) = self.value_by_name(name) {
570 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
571 flags & f.value() != 0
572 } else {
573 false
574 }
575 }
576 }
577
578 pub fn is_set_by_nick(&self, value: &Value, nick: &str) -> bool {
581 unsafe {
582 if self.type_() != value.type_() {
583 return false;
584 }
585
586 if let Some(f) = self.value_by_nick(nick) {
587 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
588 flags & f.value() != 0
589 } else {
590 false
591 }
592 }
593 }
594
595 #[doc(alias = "g_value_set_flags")]
602 pub fn set(&self, mut value: Value, f: u32) -> Result<Value, Value> {
603 unsafe {
604 if self.type_() != value.type_() {
605 return Err(value);
606 }
607
608 if let Some(f) = self.value(f) {
609 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
610 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value());
611 Ok(value)
612 } else {
613 Err(value)
614 }
615 }
616 }
617
618 pub fn set_by_name(&self, mut value: Value, name: &str) -> Result<Value, Value> {
625 unsafe {
626 if self.type_() != value.type_() {
627 return Err(value);
628 }
629
630 if let Some(f) = self.value_by_name(name) {
631 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
632 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value());
633 Ok(value)
634 } else {
635 Err(value)
636 }
637 }
638 }
639
640 pub fn set_by_nick(&self, mut value: Value, nick: &str) -> Result<Value, Value> {
647 unsafe {
648 if self.type_() != value.type_() {
649 return Err(value);
650 }
651
652 if let Some(f) = self.value_by_nick(nick) {
653 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
654 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value());
655 Ok(value)
656 } else {
657 Err(value)
658 }
659 }
660 }
661
662 pub fn unset(&self, mut value: Value, f: u32) -> Result<Value, Value> {
669 unsafe {
670 if self.type_() != value.type_() {
671 return Err(value);
672 }
673
674 if let Some(f) = self.value(f) {
675 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
676 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value());
677 Ok(value)
678 } else {
679 Err(value)
680 }
681 }
682 }
683
684 pub fn unset_by_name(&self, mut value: Value, name: &str) -> Result<Value, Value> {
691 unsafe {
692 if self.type_() != value.type_() {
693 return Err(value);
694 }
695
696 if let Some(f) = self.value_by_name(name) {
697 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
698 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value());
699 Ok(value)
700 } else {
701 Err(value)
702 }
703 }
704 }
705
706 pub fn unset_by_nick(&self, mut value: Value, nick: &str) -> Result<Value, Value> {
713 unsafe {
714 if self.type_() != value.type_() {
715 return Err(value);
716 }
717
718 if let Some(f) = self.value_by_nick(nick) {
719 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
720 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value());
721 Ok(value)
722 } else {
723 Err(value)
724 }
725 }
726 }
727
728 pub fn to_nick_string(&self, mut value: u32) -> String {
731 let mut s = String::new();
732 for val in self.values() {
733 let v = val.value();
734 if v != 0 && (value & v) == v {
735 value &= !v;
736 if !s.is_empty() {
737 s.push('|');
738 }
739 s.push_str(val.nick());
740 }
741 }
742 s
743 }
744
745 pub fn from_nick_string(&self, s: &str) -> Result<u32, ParseFlagsError> {
748 s.split('|').try_fold(0u32, |acc, flag| {
749 self.value_by_nick(flag.trim())
750 .map(|v| acc + v.value())
751 .ok_or_else(|| ParseFlagsError(flag.to_owned()))
752 })
753 }
754
755 pub fn builder(&self) -> FlagsBuilder<'_> {
759 FlagsBuilder::new(self)
760 }
761
762 pub fn builder_with_value(&self, value: Value) -> Option<FlagsBuilder<'_>> {
766 if self.type_() != value.type_() {
767 return None;
768 }
769
770 Some(FlagsBuilder::with_value(self, value))
771 }
772
773 #[doc(alias = "g_flags_complete_type_info")]
783 pub fn complete_type_info(
784 type_: Type,
785 const_static_values: &'static FlagsValues,
786 ) -> Option<TypeInfo> {
787 unsafe {
788 let is_flags: bool = from_glib(gobject_ffi::g_type_is_a(
789 type_.into_glib(),
790 gobject_ffi::G_TYPE_FLAGS,
791 ));
792 if !is_flags {
793 return None;
794 }
795
796 let info = TypeInfo::default();
797 gobject_ffi::g_flags_complete_type_info(
798 type_.into_glib(),
799 info.as_ptr(),
800 const_static_values.to_glib_none().0,
801 );
802 Some(info)
803 }
804 }
805}
806
807impl Drop for FlagsClass {
808 #[inline]
809 fn drop(&mut self) {
810 unsafe {
811 gobject_ffi::g_type_class_unref(self.0.as_ptr() as *mut _);
812 }
813 }
814}
815
816impl Clone for FlagsClass {
817 #[inline]
818 fn clone(&self) -> Self {
819 unsafe {
820 Self(ptr::NonNull::new(gobject_ffi::g_type_class_ref(self.type_().into_glib()) as *mut _).unwrap())
821 }
822 }
823}
824
825#[derive(Debug)]
826pub struct ParseFlagsError(String);
827
828impl std::error::Error for ParseFlagsError {}
829
830impl fmt::Display for ParseFlagsError {
831 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
832 write!(f, "Unknown flag: '{}'", self.0)
833 }
834}
835
836impl ParseFlagsError {
837 pub fn flag(&self) -> &str {
838 &self.0
839 }
840}
841
842#[doc(alias = "GFlagsValue")]
845#[derive(Copy, Clone)]
846#[repr(transparent)]
847pub struct FlagsValue(gobject_ffi::GFlagsValue);
848
849unsafe impl Send for FlagsValue {}
850unsafe impl Sync for FlagsValue {}
851
852impl fmt::Debug for FlagsValue {
853 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
854 f.debug_struct("FlagsValue")
855 .field("value", &self.value())
856 .field("name", &self.name())
857 .field("nick", &self.nick())
858 .finish()
859 }
860}
861
862impl FlagsValue {
863 pub const unsafe fn unsafe_from(g_value: gobject_ffi::GFlagsValue) -> Self {
869 Self(g_value)
870 }
871
872 #[doc(alias = "get_value")]
875 pub fn value(&self) -> u32 {
876 self.0.value
877 }
878
879 #[doc(alias = "get_name")]
882 pub fn name(&self) -> &str {
883 unsafe { CStr::from_ptr(self.0.value_name).to_str().unwrap() }
884 }
885
886 #[doc(alias = "get_nick")]
889 pub fn nick(&self) -> &str {
890 unsafe { CStr::from_ptr(self.0.value_nick).to_str().unwrap() }
891 }
892
893 pub fn to_value(&self, flags: &FlagsClass) -> Value {
896 unsafe {
897 let mut v = Value::from_type_unchecked(flags.type_());
898 gobject_ffi::g_value_set_flags(v.to_glib_none_mut().0, self.0.value);
899 v
900 }
901 }
902
903 pub fn from_value(value: &Value) -> Option<(FlagsClass, Vec<&FlagsValue>)> {
906 unsafe {
907 let flags_class = FlagsClass::with_type(value.type_())?;
908 let mut res = Vec::new();
909 let f = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
910 for v in flags_class.values() {
911 if v.value() & f != 0 {
912 res.push(&*(v as *const FlagsValue));
913 }
914 }
915 Some((flags_class, res))
916 }
917 }
918}
919
920impl PartialEq for FlagsValue {
921 fn eq(&self, other: &Self) -> bool {
922 self.value().eq(&other.value())
923 }
924}
925
926impl Eq for FlagsValue {}
927
928impl UnsafeFrom<gobject_ffi::GFlagsValue> for FlagsValue {
929 unsafe fn unsafe_from(g_value: gobject_ffi::GFlagsValue) -> Self {
930 Self::unsafe_from(g_value)
931 }
932}
933
934impl EnumerationValue<FlagsValue> for FlagsValue {
937 type GlibType = gobject_ffi::GFlagsValue;
938 const ZERO: FlagsValue = unsafe {
939 FlagsValue::unsafe_from(gobject_ffi::GFlagsValue {
940 value: 0,
941 value_name: ptr::null(),
942 value_nick: ptr::null(),
943 })
944 };
945}
946
947pub type FlagsValuesStorage<const N: usize> = EnumerationValuesStorage<FlagsValue, N>;
950
951pub type FlagsValues = EnumerationValues<FlagsValue>;
954
955#[must_use = "The builder must be built to be used"]
974pub struct FlagsBuilder<'a>(&'a FlagsClass, Option<Value>);
975impl FlagsBuilder<'_> {
976 fn new(flags_class: &FlagsClass) -> FlagsBuilder<'_> {
977 let value = unsafe { Value::from_type_unchecked(flags_class.type_()) };
978 FlagsBuilder(flags_class, Some(value))
979 }
980
981 fn with_value(flags_class: &FlagsClass, value: Value) -> FlagsBuilder<'_> {
982 FlagsBuilder(flags_class, Some(value))
983 }
984
985 pub fn set(mut self, f: u32) -> Self {
988 if let Some(value) = self.1.take() {
989 self.1 = self.0.set(value, f).ok();
990 }
991
992 self
993 }
994
995 pub fn set_by_name(mut self, name: &str) -> Self {
998 if let Some(value) = self.1.take() {
999 self.1 = self.0.set_by_name(value, name).ok();
1000 }
1001
1002 self
1003 }
1004
1005 pub fn set_by_nick(mut self, nick: &str) -> Self {
1008 if let Some(value) = self.1.take() {
1009 self.1 = self.0.set_by_nick(value, nick).ok();
1010 }
1011
1012 self
1013 }
1014
1015 pub fn unset(mut self, f: u32) -> Self {
1018 if let Some(value) = self.1.take() {
1019 self.1 = self.0.unset(value, f).ok();
1020 }
1021
1022 self
1023 }
1024
1025 pub fn unset_by_name(mut self, name: &str) -> Self {
1028 if let Some(value) = self.1.take() {
1029 self.1 = self.0.unset_by_name(value, name).ok();
1030 }
1031
1032 self
1033 }
1034
1035 pub fn unset_by_nick(mut self, nick: &str) -> Self {
1038 if let Some(value) = self.1.take() {
1039 self.1 = self.0.unset_by_nick(value, nick).ok();
1040 }
1041
1042 self
1043 }
1044
1045 #[must_use = "Value returned from the builder should probably be used"]
1048 pub fn build(self) -> Option<Value> {
1049 self.1
1050 }
1051}
1052
1053unsafe impl<'a> crate::value::FromValue<'a> for Vec<&FlagsValue> {
1054 type Checker = FlagsTypeChecker;
1055
1056 unsafe fn from_value(value: &'a Value) -> Self {
1057 let (_, v) = FlagsValue::from_value(value).unwrap();
1058 std::mem::transmute(v)
1060 }
1061}
1062
1063pub struct FlagsTypeChecker();
1064unsafe impl crate::value::ValueTypeChecker for FlagsTypeChecker {
1065 type Error = InvalidFlagsError;
1066
1067 fn check(value: &Value) -> Result<(), Self::Error> {
1068 let t = value.type_();
1069 if t.is_a(Type::FLAGS) {
1070 Ok(())
1071 } else {
1072 Err(InvalidFlagsError)
1073 }
1074 }
1075}
1076
1077#[derive(Clone, PartialEq, Eq, Debug)]
1081pub struct InvalidFlagsError;
1082
1083impl fmt::Display for InvalidFlagsError {
1084 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1085 write!(f, "Value is not a flags")
1086 }
1087}
1088
1089impl std::error::Error for InvalidFlagsError {}
1090
1091pub trait EnumerationValue<E>: Copy {
1094 type GlibType;
1095 const ZERO: E;
1096}
1097
1098#[repr(C)]
1109pub struct EnumerationValuesStorage<E: EnumerationValue<E>, const S: usize>([E; S]);
1110
1111impl<E: EnumerationValue<E>, const S: usize> EnumerationValuesStorage<E, S> {
1112 pub const fn new<const N: usize>(values: [E; N]) -> Self {
1115 #[repr(C)]
1116 #[derive(Copy, Clone)]
1117 struct Both<E: Copy, const N: usize>([E; N], [E; 1]);
1118
1119 #[repr(C)]
1120 union Transmute<E: Copy, const N: usize, const S: usize> {
1121 from: Both<E, N>,
1122 to: [E; S],
1123 }
1124
1125 unsafe {
1127 let all = Transmute {
1129 from: Both(values, [E::ZERO; 1]),
1130 }
1131 .to;
1132 Self(all)
1133 }
1134 }
1135}
1136
1137impl<E: EnumerationValue<E>, const S: usize> AsRef<EnumerationValues<E>>
1138 for EnumerationValuesStorage<E, S>
1139{
1140 fn as_ref(&self) -> &EnumerationValues<E> {
1141 unsafe { &*(&self.0 as *const [E] as *const EnumerationValues<E>) }
1143 }
1144}
1145
1146#[repr(C)]
1157pub struct EnumerationValues<E: EnumerationValue<E>>([E]);
1158
1159impl<E: EnumerationValue<E>> Deref for EnumerationValues<E> {
1160 type Target = [E];
1161
1162 fn deref(&self) -> &Self::Target {
1165 unsafe { std::slice::from_raw_parts(self.0.as_ptr(), self.0.len() - 1) }
1167 }
1168}
1169
1170#[doc(hidden)]
1171impl<'a, E: 'a + EnumerationValue<E>> ToGlibPtr<'a, *const E::GlibType> for EnumerationValues<E> {
1172 type Storage = &'a Self;
1173
1174 fn to_glib_none(&'a self) -> Stash<'a, *const E::GlibType, Self> {
1175 Stash(self.0.as_ptr() as *const E::GlibType, self)
1176 }
1177}
1178
1179#[cfg(test)]
1180mod tests {
1181 use super::*;
1182
1183 #[test]
1184 fn test_flags() {
1185 let flags = FlagsClass::new::<crate::BindingFlags>();
1186 let values = flags.values();
1187 let def1 = values
1188 .iter()
1189 .find(|v| v.name() == "G_BINDING_DEFAULT")
1190 .unwrap();
1191 let def2 = flags.value_by_name("G_BINDING_DEFAULT").unwrap();
1192 assert!(ptr::eq(def1, def2));
1193
1194 let value = flags.to_value(0).unwrap();
1195 let values = value.get::<Vec<&FlagsValue>>().unwrap();
1196 assert_eq!(values.len(), 0);
1197
1198 assert_eq!(def1.value(), crate::BindingFlags::DEFAULT.bits());
1199 }
1200}