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")]
255#[derive(Copy, Clone)]
256#[repr(transparent)]
257pub struct EnumValue(gobject_ffi::GEnumValue);
258
259unsafe impl Send for EnumValue {}
260unsafe impl Sync for EnumValue {}
261
262impl fmt::Debug for EnumValue {
263 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
264 f.debug_struct("EnumValue")
265 .field("value", &self.value())
266 .field("name", &self.name())
267 .field("nick", &self.nick())
268 .finish()
269 }
270}
271
272impl EnumValue {
273 pub const unsafe fn unsafe_from(g_value: gobject_ffi::GEnumValue) -> Self {
279 Self(g_value)
280 }
281
282 #[doc(alias = "get_value")]
285 pub fn value(&self) -> i32 {
286 self.0.value
287 }
288
289 #[doc(alias = "get_name")]
292 pub fn name(&self) -> &str {
293 unsafe { CStr::from_ptr(self.0.value_name).to_str().unwrap() }
294 }
295
296 #[doc(alias = "get_nick")]
299 pub fn nick(&self) -> &str {
300 unsafe { CStr::from_ptr(self.0.value_nick).to_str().unwrap() }
301 }
302
303 pub fn to_value(&self, enum_: &EnumClass) -> Value {
306 unsafe {
307 let mut v = Value::from_type_unchecked(enum_.type_());
308 gobject_ffi::g_value_set_enum(v.to_glib_none_mut().0, self.0.value);
309 v
310 }
311 }
312
313 pub fn from_value(value: &Value) -> Option<(EnumClass, &EnumValue)> {
316 unsafe {
317 let enum_class = EnumClass::with_type(value.type_())?;
318 let v = enum_class.value(gobject_ffi::g_value_get_enum(value.to_glib_none().0))?;
319 let v = &*(v as *const EnumValue);
320 Some((enum_class, v))
321 }
322 }
323}
324
325impl PartialEq for EnumValue {
326 fn eq(&self, other: &Self) -> bool {
327 self.value().eq(&other.value())
328 }
329}
330
331impl Eq for EnumValue {}
332
333impl PartialOrd for EnumValue {
334 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
335 Some(self.cmp(other))
336 }
337}
338
339impl Ord for EnumValue {
340 fn cmp(&self, other: &Self) -> cmp::Ordering {
341 self.value().cmp(&other.value())
342 }
343}
344
345impl UnsafeFrom<gobject_ffi::GEnumValue> for EnumValue {
346 unsafe fn unsafe_from(g_value: gobject_ffi::GEnumValue) -> Self {
347 Self::unsafe_from(g_value)
348 }
349}
350
351unsafe impl<'a> crate::value::FromValue<'a> for &EnumValue {
352 type Checker = EnumTypeChecker;
353
354 unsafe fn from_value(value: &'a Value) -> Self {
355 let (_, v) = EnumValue::from_value(value).unwrap();
356 std::mem::transmute(v)
358 }
359}
360
361impl EnumerationValue<EnumValue> for EnumValue {
364 type GlibType = gobject_ffi::GEnumValue;
365 const ZERO: EnumValue = unsafe {
366 EnumValue::unsafe_from(gobject_ffi::GEnumValue {
367 value: 0,
368 value_name: ptr::null(),
369 value_nick: ptr::null(),
370 })
371 };
372}
373
374pub type EnumValuesStorage<const N: usize> = EnumerationValuesStorage<EnumValue, N>;
377
378pub type EnumValues = EnumerationValues<EnumValue>;
381
382pub struct EnumTypeChecker();
383unsafe impl crate::value::ValueTypeChecker for EnumTypeChecker {
384 type Error = InvalidEnumError;
385
386 fn check(value: &Value) -> Result<(), Self::Error> {
387 let t = value.type_();
388 if t.is_a(Type::ENUM) {
389 Ok(())
390 } else {
391 Err(InvalidEnumError)
392 }
393 }
394}
395
396#[derive(Clone, PartialEq, Eq, Debug)]
400pub struct InvalidEnumError;
401
402impl fmt::Display for InvalidEnumError {
403 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
404 write!(f, "Value is not an enum")
405 }
406}
407
408impl std::error::Error for InvalidEnumError {}
409
410#[doc(alias = "GFlagsClass")]
414#[repr(transparent)]
415pub struct FlagsClass(ptr::NonNull<gobject_ffi::GFlagsClass>);
416
417unsafe impl Send for FlagsClass {}
418unsafe impl Sync for FlagsClass {}
419
420impl fmt::Debug for FlagsClass {
421 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
422 f.debug_struct("FlagsClass")
423 .field("type", &self.type_())
424 .field("values", &self.values())
425 .finish()
426 }
427}
428
429impl FlagsClass {
430 pub fn new<T: StaticType + HasParamSpec<ParamSpec = ParamSpecFlags>>() -> Self {
435 Self::with_type(T::static_type()).expect("invalid flags class")
436 }
437 pub fn with_type(type_: Type) -> Option<Self> {
442 unsafe {
443 let is_flags: bool = from_glib(gobject_ffi::g_type_is_a(
444 type_.into_glib(),
445 gobject_ffi::G_TYPE_FLAGS,
446 ));
447 if !is_flags {
448 return None;
449 }
450
451 Some(FlagsClass(
452 ptr::NonNull::new(gobject_ffi::g_type_class_ref(type_.into_glib()) as *mut _)
453 .unwrap(),
454 ))
455 }
456 }
457
458 pub fn type_(&self) -> Type {
461 unsafe { from_glib(self.0.as_ref().g_type_class.g_type) }
462 }
463
464 #[doc(alias = "g_flags_get_first_value")]
470 #[doc(alias = "get_value")]
471 pub fn value(&self, value: u32) -> Option<&FlagsValue> {
472 unsafe {
473 let v = gobject_ffi::g_flags_get_first_value(self.0.as_ptr(), value);
474 if v.is_null() {
475 None
476 } else {
477 Some(&*(v as *const FlagsValue))
478 }
479 }
480 }
481
482 #[doc(alias = "g_flags_get_value_by_name")]
488 #[doc(alias = "get_value_by_name")]
489 pub fn value_by_name(&self, name: &str) -> Option<&FlagsValue> {
490 unsafe {
491 let v = gobject_ffi::g_flags_get_value_by_name(self.0.as_ptr(), name.to_glib_none().0);
492 if v.is_null() {
493 None
494 } else {
495 Some(&*(v as *const FlagsValue))
496 }
497 }
498 }
499
500 #[doc(alias = "g_flags_get_value_by_nick")]
506 #[doc(alias = "get_value_by_nick")]
507 pub fn value_by_nick(&self, nick: &str) -> Option<&FlagsValue> {
508 unsafe {
509 let v = gobject_ffi::g_flags_get_value_by_nick(self.0.as_ptr(), nick.to_glib_none().0);
510 if v.is_null() {
511 None
512 } else {
513 Some(&*(v as *const FlagsValue))
514 }
515 }
516 }
517
518 #[doc(alias = "get_values")]
521 pub fn values(&self) -> &[FlagsValue] {
522 unsafe {
523 if self.0.as_ref().n_values == 0 {
524 return &[];
525 }
526 std::slice::from_raw_parts(
527 self.0.as_ref().values as *const FlagsValue,
528 self.0.as_ref().n_values as usize,
529 )
530 }
531 }
532
533 pub fn to_value(&self, value: u32) -> Option<Value> {
536 self.value(value).map(|v| v.to_value(self))
537 }
538
539 pub fn to_value_by_name(&self, name: &str) -> Option<Value> {
542 self.value_by_name(name).map(|v| v.to_value(self))
543 }
544
545 pub fn to_value_by_nick(&self, nick: &str) -> Option<Value> {
548 self.value_by_nick(nick).map(|v| v.to_value(self))
549 }
550
551 pub fn is_set(&self, value: &Value, f: u32) -> bool {
554 unsafe {
555 if self.type_() != value.type_() {
556 return false;
557 }
558
559 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
560 flags & f != 0
561 }
562 }
563
564 pub fn is_set_by_name(&self, value: &Value, name: &str) -> bool {
567 unsafe {
568 if self.type_() != value.type_() {
569 return false;
570 }
571
572 if let Some(f) = self.value_by_name(name) {
573 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
574 flags & f.value() != 0
575 } else {
576 false
577 }
578 }
579 }
580
581 pub fn is_set_by_nick(&self, value: &Value, nick: &str) -> bool {
584 unsafe {
585 if self.type_() != value.type_() {
586 return false;
587 }
588
589 if let Some(f) = self.value_by_nick(nick) {
590 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
591 flags & f.value() != 0
592 } else {
593 false
594 }
595 }
596 }
597
598 #[doc(alias = "g_value_set_flags")]
605 pub fn set(&self, mut value: Value, f: u32) -> Result<Value, Value> {
606 unsafe {
607 if self.type_() != value.type_() {
608 return Err(value);
609 }
610
611 if let Some(f) = self.value(f) {
612 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
613 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value());
614 Ok(value)
615 } else {
616 Err(value)
617 }
618 }
619 }
620
621 pub fn set_by_name(&self, mut value: Value, name: &str) -> Result<Value, Value> {
628 unsafe {
629 if self.type_() != value.type_() {
630 return Err(value);
631 }
632
633 if let Some(f) = self.value_by_name(name) {
634 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
635 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value());
636 Ok(value)
637 } else {
638 Err(value)
639 }
640 }
641 }
642
643 pub fn set_by_nick(&self, mut value: Value, nick: &str) -> Result<Value, Value> {
650 unsafe {
651 if self.type_() != value.type_() {
652 return Err(value);
653 }
654
655 if let Some(f) = self.value_by_nick(nick) {
656 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
657 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value());
658 Ok(value)
659 } else {
660 Err(value)
661 }
662 }
663 }
664
665 pub fn unset(&self, mut value: Value, f: u32) -> Result<Value, Value> {
672 unsafe {
673 if self.type_() != value.type_() {
674 return Err(value);
675 }
676
677 if let Some(f) = self.value(f) {
678 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
679 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value());
680 Ok(value)
681 } else {
682 Err(value)
683 }
684 }
685 }
686
687 pub fn unset_by_name(&self, mut value: Value, name: &str) -> Result<Value, Value> {
694 unsafe {
695 if self.type_() != value.type_() {
696 return Err(value);
697 }
698
699 if let Some(f) = self.value_by_name(name) {
700 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
701 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value());
702 Ok(value)
703 } else {
704 Err(value)
705 }
706 }
707 }
708
709 pub fn unset_by_nick(&self, mut value: Value, nick: &str) -> Result<Value, Value> {
716 unsafe {
717 if self.type_() != value.type_() {
718 return Err(value);
719 }
720
721 if let Some(f) = self.value_by_nick(nick) {
722 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
723 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value());
724 Ok(value)
725 } else {
726 Err(value)
727 }
728 }
729 }
730
731 pub fn to_nick_string(&self, mut value: u32) -> String {
734 let mut s = String::new();
735 for val in self.values() {
736 let v = val.value();
737 if v != 0 && (value & v) == v {
738 value &= !v;
739 if !s.is_empty() {
740 s.push('|');
741 }
742 s.push_str(val.nick());
743 }
744 }
745 s
746 }
747
748 pub fn from_nick_string(&self, s: &str) -> Result<u32, ParseFlagsError> {
751 s.split('|').try_fold(0u32, |acc, flag| {
752 self.value_by_nick(flag.trim())
753 .map(|v| acc + v.value())
754 .ok_or_else(|| ParseFlagsError(flag.to_owned()))
755 })
756 }
757
758 pub fn builder(&self) -> FlagsBuilder {
762 FlagsBuilder::new(self)
763 }
764
765 pub fn builder_with_value(&self, value: Value) -> Option<FlagsBuilder> {
769 if self.type_() != value.type_() {
770 return None;
771 }
772
773 Some(FlagsBuilder::with_value(self, value))
774 }
775
776 #[doc(alias = "g_flags_complete_type_info")]
786 pub fn complete_type_info(
787 type_: Type,
788 const_static_values: &'static FlagsValues,
789 ) -> Option<TypeInfo> {
790 unsafe {
791 let is_flags: bool = from_glib(gobject_ffi::g_type_is_a(
792 type_.into_glib(),
793 gobject_ffi::G_TYPE_FLAGS,
794 ));
795 if !is_flags {
796 return None;
797 }
798
799 let info = TypeInfo::default();
800 gobject_ffi::g_flags_complete_type_info(
801 type_.into_glib(),
802 info.as_ptr(),
803 const_static_values.to_glib_none().0,
804 );
805 Some(info)
806 }
807 }
808}
809
810impl Drop for FlagsClass {
811 #[inline]
812 fn drop(&mut self) {
813 unsafe {
814 gobject_ffi::g_type_class_unref(self.0.as_ptr() as *mut _);
815 }
816 }
817}
818
819impl Clone for FlagsClass {
820 #[inline]
821 fn clone(&self) -> Self {
822 unsafe {
823 Self(ptr::NonNull::new(gobject_ffi::g_type_class_ref(self.type_().into_glib()) as *mut _).unwrap())
824 }
825 }
826}
827
828#[derive(Debug)]
829pub struct ParseFlagsError(String);
830
831impl std::error::Error for ParseFlagsError {}
832
833impl fmt::Display for ParseFlagsError {
834 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
835 write!(f, "Unknown flag: '{}'", self.0)
836 }
837}
838
839impl ParseFlagsError {
840 pub fn flag(&self) -> &str {
841 &self.0
842 }
843}
844
845#[doc(alias = "GFlagsValue")]
851#[derive(Copy, Clone)]
852#[repr(transparent)]
853pub struct FlagsValue(gobject_ffi::GFlagsValue);
854
855unsafe impl Send for FlagsValue {}
856unsafe impl Sync for FlagsValue {}
857
858impl fmt::Debug for FlagsValue {
859 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
860 f.debug_struct("FlagsValue")
861 .field("value", &self.value())
862 .field("name", &self.name())
863 .field("nick", &self.nick())
864 .finish()
865 }
866}
867
868impl FlagsValue {
869 pub const unsafe fn unsafe_from(g_value: gobject_ffi::GFlagsValue) -> Self {
875 Self(g_value)
876 }
877
878 #[doc(alias = "get_value")]
881 pub fn value(&self) -> u32 {
882 self.0.value
883 }
884
885 #[doc(alias = "get_name")]
888 pub fn name(&self) -> &str {
889 unsafe { CStr::from_ptr(self.0.value_name).to_str().unwrap() }
890 }
891
892 #[doc(alias = "get_nick")]
895 pub fn nick(&self) -> &str {
896 unsafe { CStr::from_ptr(self.0.value_nick).to_str().unwrap() }
897 }
898
899 pub fn to_value(&self, flags: &FlagsClass) -> Value {
902 unsafe {
903 let mut v = Value::from_type_unchecked(flags.type_());
904 gobject_ffi::g_value_set_flags(v.to_glib_none_mut().0, self.0.value);
905 v
906 }
907 }
908
909 pub fn from_value(value: &Value) -> Option<(FlagsClass, Vec<&FlagsValue>)> {
912 unsafe {
913 let flags_class = FlagsClass::with_type(value.type_())?;
914 let mut res = Vec::new();
915 let f = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
916 for v in flags_class.values() {
917 if v.value() & f != 0 {
918 res.push(&*(v as *const FlagsValue));
919 }
920 }
921 Some((flags_class, res))
922 }
923 }
924}
925
926impl PartialEq for FlagsValue {
927 fn eq(&self, other: &Self) -> bool {
928 self.value().eq(&other.value())
929 }
930}
931
932impl Eq for FlagsValue {}
933
934impl UnsafeFrom<gobject_ffi::GFlagsValue> for FlagsValue {
935 unsafe fn unsafe_from(g_value: gobject_ffi::GFlagsValue) -> Self {
936 Self::unsafe_from(g_value)
937 }
938}
939
940impl EnumerationValue<FlagsValue> for FlagsValue {
943 type GlibType = gobject_ffi::GFlagsValue;
944 const ZERO: FlagsValue = unsafe {
945 FlagsValue::unsafe_from(gobject_ffi::GFlagsValue {
946 value: 0,
947 value_name: ptr::null(),
948 value_nick: ptr::null(),
949 })
950 };
951}
952
953pub type FlagsValuesStorage<const N: usize> = EnumerationValuesStorage<FlagsValue, N>;
956
957pub type FlagsValues = EnumerationValues<FlagsValue>;
960
961#[must_use = "The builder must be built to be used"]
980pub struct FlagsBuilder<'a>(&'a FlagsClass, Option<Value>);
981impl FlagsBuilder<'_> {
982 fn new(flags_class: &FlagsClass) -> FlagsBuilder {
983 let value = unsafe { Value::from_type_unchecked(flags_class.type_()) };
984 FlagsBuilder(flags_class, Some(value))
985 }
986
987 fn with_value(flags_class: &FlagsClass, value: Value) -> FlagsBuilder {
988 FlagsBuilder(flags_class, Some(value))
989 }
990
991 pub fn set(mut self, f: u32) -> Self {
994 if let Some(value) = self.1.take() {
995 self.1 = self.0.set(value, f).ok();
996 }
997
998 self
999 }
1000
1001 pub fn set_by_name(mut self, name: &str) -> Self {
1004 if let Some(value) = self.1.take() {
1005 self.1 = self.0.set_by_name(value, name).ok();
1006 }
1007
1008 self
1009 }
1010
1011 pub fn set_by_nick(mut self, nick: &str) -> Self {
1014 if let Some(value) = self.1.take() {
1015 self.1 = self.0.set_by_nick(value, nick).ok();
1016 }
1017
1018 self
1019 }
1020
1021 pub fn unset(mut self, f: u32) -> Self {
1024 if let Some(value) = self.1.take() {
1025 self.1 = self.0.unset(value, f).ok();
1026 }
1027
1028 self
1029 }
1030
1031 pub fn unset_by_name(mut self, name: &str) -> Self {
1034 if let Some(value) = self.1.take() {
1035 self.1 = self.0.unset_by_name(value, name).ok();
1036 }
1037
1038 self
1039 }
1040
1041 pub fn unset_by_nick(mut self, nick: &str) -> Self {
1044 if let Some(value) = self.1.take() {
1045 self.1 = self.0.unset_by_nick(value, nick).ok();
1046 }
1047
1048 self
1049 }
1050
1051 #[must_use = "Value returned from the builder should probably be used"]
1054 pub fn build(self) -> Option<Value> {
1055 self.1
1056 }
1057}
1058
1059unsafe impl<'a> crate::value::FromValue<'a> for Vec<&FlagsValue> {
1060 type Checker = FlagsTypeChecker;
1061
1062 unsafe fn from_value(value: &'a Value) -> Self {
1063 let (_, v) = FlagsValue::from_value(value).unwrap();
1064 std::mem::transmute(v)
1066 }
1067}
1068
1069pub struct FlagsTypeChecker();
1070unsafe impl crate::value::ValueTypeChecker for FlagsTypeChecker {
1071 type Error = InvalidFlagsError;
1072
1073 fn check(value: &Value) -> Result<(), Self::Error> {
1074 let t = value.type_();
1075 if t.is_a(Type::FLAGS) {
1076 Ok(())
1077 } else {
1078 Err(InvalidFlagsError)
1079 }
1080 }
1081}
1082
1083#[derive(Clone, PartialEq, Eq, Debug)]
1087pub struct InvalidFlagsError;
1088
1089impl fmt::Display for InvalidFlagsError {
1090 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1091 write!(f, "Value is not a flags")
1092 }
1093}
1094
1095impl std::error::Error for InvalidFlagsError {}
1096
1097pub trait EnumerationValue<E>: Copy {
1100 type GlibType;
1101 const ZERO: E;
1102}
1103
1104#[repr(C)]
1115pub struct EnumerationValuesStorage<E: EnumerationValue<E>, const S: usize>([E; S]);
1116
1117impl<E: EnumerationValue<E>, const S: usize> EnumerationValuesStorage<E, S> {
1118 pub const fn new<const N: usize>(values: [E; N]) -> Self {
1121 #[repr(C)]
1122 #[derive(Copy, Clone)]
1123 struct Both<E: Copy, const N: usize>([E; N], [E; 1]);
1124
1125 #[repr(C)]
1126 union Transmute<E: Copy, const N: usize, const S: usize> {
1127 from: Both<E, N>,
1128 to: [E; S],
1129 }
1130
1131 unsafe {
1133 let all = Transmute {
1135 from: Both(values, [E::ZERO; 1]),
1136 }
1137 .to;
1138 Self(all)
1139 }
1140 }
1141}
1142
1143impl<E: EnumerationValue<E>, const S: usize> AsRef<EnumerationValues<E>>
1144 for EnumerationValuesStorage<E, S>
1145{
1146 fn as_ref(&self) -> &EnumerationValues<E> {
1147 unsafe { &*(&self.0 as *const [E] as *const EnumerationValues<E>) }
1149 }
1150}
1151
1152#[repr(C)]
1163pub struct EnumerationValues<E: EnumerationValue<E>>([E]);
1164
1165impl<E: EnumerationValue<E>> Deref for EnumerationValues<E> {
1166 type Target = [E];
1167
1168 fn deref(&self) -> &Self::Target {
1171 unsafe { std::slice::from_raw_parts(self.0.as_ptr(), self.0.len() - 1) }
1173 }
1174}
1175
1176#[doc(hidden)]
1177impl<'a, E: 'a + EnumerationValue<E>> ToGlibPtr<'a, *const E::GlibType> for EnumerationValues<E> {
1178 type Storage = &'a Self;
1179
1180 fn to_glib_none(&'a self) -> Stash<'a, *const E::GlibType, Self> {
1181 Stash(self.0.as_ptr() as *const E::GlibType, self)
1182 }
1183}
1184
1185#[cfg(test)]
1186mod tests {
1187 use super::*;
1188
1189 #[test]
1190 fn test_flags() {
1191 let flags = FlagsClass::new::<crate::BindingFlags>();
1192 let values = flags.values();
1193 let def1 = values
1194 .iter()
1195 .find(|v| v.name() == "G_BINDING_DEFAULT")
1196 .unwrap();
1197 let def2 = flags.value_by_name("G_BINDING_DEFAULT").unwrap();
1198 assert!(ptr::eq(def1, def2));
1199
1200 let value = flags.to_value(0).unwrap();
1201 let values = value.get::<Vec<&FlagsValue>>().unwrap();
1202 assert_eq!(values.len(), 0);
1203
1204 assert_eq!(def1.value(), crate::BindingFlags::DEFAULT.bits());
1205 }
1206}