1use std::{cmp, ffi::CStr, fmt, ops::Deref, ptr};
4
5use crate::{
6 ParamSpecEnum, ParamSpecFlags, Type, TypeInfo, Value, ffi, gobject_ffi, prelude::*,
7 translate::*,
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 unsafe { 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 unsafe {
356 let (_, v) = EnumValue::from_value(value).unwrap();
357 std::mem::transmute(v)
359 }
360 }
361}
362
363impl EnumerationValue<EnumValue> for EnumValue {
366 type GlibType = gobject_ffi::GEnumValue;
367 const ZERO: EnumValue = unsafe {
368 EnumValue::unsafe_from(gobject_ffi::GEnumValue {
369 value: 0,
370 value_name: ptr::null(),
371 value_nick: ptr::null(),
372 })
373 };
374}
375
376pub type EnumValuesStorage<const N: usize> = EnumerationValuesStorage<EnumValue, N>;
379
380pub type EnumValues = EnumerationValues<EnumValue>;
383
384pub struct EnumTypeChecker();
385unsafe impl crate::value::ValueTypeChecker for EnumTypeChecker {
386 type Error = InvalidEnumError;
387
388 fn check(value: &Value) -> Result<(), Self::Error> {
389 let t = value.type_();
390 if t.is_a(Type::ENUM) {
391 Ok(())
392 } else {
393 Err(InvalidEnumError)
394 }
395 }
396}
397
398#[derive(Clone, PartialEq, Eq, Debug)]
402pub struct InvalidEnumError;
403
404impl fmt::Display for InvalidEnumError {
405 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
406 write!(f, "Value is not an enum")
407 }
408}
409
410impl std::error::Error for InvalidEnumError {}
411
412#[doc(alias = "GFlagsClass")]
416#[repr(transparent)]
417pub struct FlagsClass(ptr::NonNull<gobject_ffi::GFlagsClass>);
418
419unsafe impl Send for FlagsClass {}
420unsafe impl Sync for FlagsClass {}
421
422impl fmt::Debug for FlagsClass {
423 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
424 f.debug_struct("FlagsClass")
425 .field("type", &self.type_())
426 .field("values", &self.values())
427 .finish()
428 }
429}
430
431impl FlagsClass {
432 pub fn new<T: StaticType + HasParamSpec<ParamSpec = ParamSpecFlags>>() -> Self {
437 Self::with_type(T::static_type()).expect("invalid flags class")
438 }
439 pub fn with_type(type_: Type) -> Option<Self> {
444 unsafe {
445 let is_flags: bool = from_glib(gobject_ffi::g_type_is_a(
446 type_.into_glib(),
447 gobject_ffi::G_TYPE_FLAGS,
448 ));
449 if !is_flags {
450 return None;
451 }
452
453 Some(FlagsClass(
454 ptr::NonNull::new(gobject_ffi::g_type_class_ref(type_.into_glib()) as *mut _)
455 .unwrap(),
456 ))
457 }
458 }
459
460 pub fn type_(&self) -> Type {
463 unsafe { from_glib(self.0.as_ref().g_type_class.g_type) }
464 }
465
466 #[doc(alias = "g_flags_get_first_value")]
472 #[doc(alias = "get_value")]
473 pub fn value(&self, value: u32) -> Option<&FlagsValue> {
474 unsafe {
475 let v = gobject_ffi::g_flags_get_first_value(self.0.as_ptr(), value);
476 if v.is_null() {
477 None
478 } else {
479 Some(&*(v as *const FlagsValue))
480 }
481 }
482 }
483
484 #[doc(alias = "g_flags_get_value_by_name")]
490 #[doc(alias = "get_value_by_name")]
491 pub fn value_by_name(&self, name: &str) -> Option<&FlagsValue> {
492 unsafe {
493 let v = gobject_ffi::g_flags_get_value_by_name(self.0.as_ptr(), name.to_glib_none().0);
494 if v.is_null() {
495 None
496 } else {
497 Some(&*(v as *const FlagsValue))
498 }
499 }
500 }
501
502 #[doc(alias = "g_flags_get_value_by_nick")]
508 #[doc(alias = "get_value_by_nick")]
509 pub fn value_by_nick(&self, nick: &str) -> Option<&FlagsValue> {
510 unsafe {
511 let v = gobject_ffi::g_flags_get_value_by_nick(self.0.as_ptr(), nick.to_glib_none().0);
512 if v.is_null() {
513 None
514 } else {
515 Some(&*(v as *const FlagsValue))
516 }
517 }
518 }
519
520 #[doc(alias = "get_values")]
523 pub fn values(&self) -> &[FlagsValue] {
524 unsafe {
525 if self.0.as_ref().n_values == 0 {
526 return &[];
527 }
528 std::slice::from_raw_parts(
529 self.0.as_ref().values as *const FlagsValue,
530 self.0.as_ref().n_values as usize,
531 )
532 }
533 }
534
535 pub fn to_value(&self, value: u32) -> Option<Value> {
538 self.value(value).map(|v| v.to_value(self))
539 }
540
541 pub fn to_value_by_name(&self, name: &str) -> Option<Value> {
544 self.value_by_name(name).map(|v| v.to_value(self))
545 }
546
547 pub fn to_value_by_nick(&self, nick: &str) -> Option<Value> {
550 self.value_by_nick(nick).map(|v| v.to_value(self))
551 }
552
553 pub fn is_set(&self, value: &Value, f: u32) -> bool {
556 unsafe {
557 if self.type_() != value.type_() {
558 return false;
559 }
560
561 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
562 flags & f != 0
563 }
564 }
565
566 pub fn is_set_by_name(&self, value: &Value, name: &str) -> bool {
569 unsafe {
570 if self.type_() != value.type_() {
571 return false;
572 }
573
574 if let Some(f) = self.value_by_name(name) {
575 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
576 flags & f.value() != 0
577 } else {
578 false
579 }
580 }
581 }
582
583 pub fn is_set_by_nick(&self, value: &Value, nick: &str) -> bool {
586 unsafe {
587 if self.type_() != value.type_() {
588 return false;
589 }
590
591 if let Some(f) = self.value_by_nick(nick) {
592 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
593 flags & f.value() != 0
594 } else {
595 false
596 }
597 }
598 }
599
600 #[doc(alias = "g_value_set_flags")]
607 pub fn set(&self, mut value: Value, f: u32) -> Result<Value, Value> {
608 unsafe {
609 if self.type_() != value.type_() {
610 return Err(value);
611 }
612
613 if let Some(f) = self.value(f) {
614 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
615 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value());
616 Ok(value)
617 } else {
618 Err(value)
619 }
620 }
621 }
622
623 pub fn set_by_name(&self, mut value: Value, name: &str) -> Result<Value, Value> {
630 unsafe {
631 if self.type_() != value.type_() {
632 return Err(value);
633 }
634
635 if let Some(f) = self.value_by_name(name) {
636 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
637 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value());
638 Ok(value)
639 } else {
640 Err(value)
641 }
642 }
643 }
644
645 pub fn set_by_nick(&self, mut value: Value, nick: &str) -> Result<Value, Value> {
652 unsafe {
653 if self.type_() != value.type_() {
654 return Err(value);
655 }
656
657 if let Some(f) = self.value_by_nick(nick) {
658 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
659 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value());
660 Ok(value)
661 } else {
662 Err(value)
663 }
664 }
665 }
666
667 pub fn unset(&self, mut value: Value, f: u32) -> Result<Value, Value> {
674 unsafe {
675 if self.type_() != value.type_() {
676 return Err(value);
677 }
678
679 if let Some(f) = self.value(f) {
680 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
681 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value());
682 Ok(value)
683 } else {
684 Err(value)
685 }
686 }
687 }
688
689 pub fn unset_by_name(&self, mut value: Value, name: &str) -> Result<Value, Value> {
696 unsafe {
697 if self.type_() != value.type_() {
698 return Err(value);
699 }
700
701 if let Some(f) = self.value_by_name(name) {
702 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
703 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value());
704 Ok(value)
705 } else {
706 Err(value)
707 }
708 }
709 }
710
711 pub fn unset_by_nick(&self, mut value: Value, nick: &str) -> Result<Value, Value> {
718 unsafe {
719 if self.type_() != value.type_() {
720 return Err(value);
721 }
722
723 if let Some(f) = self.value_by_nick(nick) {
724 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
725 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value());
726 Ok(value)
727 } else {
728 Err(value)
729 }
730 }
731 }
732
733 pub fn to_nick_string(&self, mut value: u32) -> String {
736 let mut s = String::new();
737 for val in self.values() {
738 let v = val.value();
739 if v != 0 && (value & v) == v {
740 value &= !v;
741 if !s.is_empty() {
742 s.push('|');
743 }
744 s.push_str(val.nick());
745 }
746 }
747 s
748 }
749
750 pub fn from_nick_string(&self, s: &str) -> Result<u32, ParseFlagsError> {
753 s.split('|').try_fold(0u32, |acc, flag| {
754 self.value_by_nick(flag.trim())
755 .map(|v| acc + v.value())
756 .ok_or_else(|| ParseFlagsError(flag.to_owned()))
757 })
758 }
759
760 pub fn builder(&self) -> FlagsBuilder<'_> {
764 FlagsBuilder::new(self)
765 }
766
767 pub fn builder_with_value(&self, value: Value) -> Option<FlagsBuilder<'_>> {
771 if self.type_() != value.type_() {
772 return None;
773 }
774
775 Some(FlagsBuilder::with_value(self, value))
776 }
777
778 #[doc(alias = "g_flags_complete_type_info")]
788 pub fn complete_type_info(
789 type_: Type,
790 const_static_values: &'static FlagsValues,
791 ) -> Option<TypeInfo> {
792 unsafe {
793 let is_flags: bool = from_glib(gobject_ffi::g_type_is_a(
794 type_.into_glib(),
795 gobject_ffi::G_TYPE_FLAGS,
796 ));
797 if !is_flags {
798 return None;
799 }
800
801 let info = TypeInfo::default();
802 gobject_ffi::g_flags_complete_type_info(
803 type_.into_glib(),
804 info.as_ptr(),
805 const_static_values.to_glib_none().0,
806 );
807 Some(info)
808 }
809 }
810}
811
812impl Drop for FlagsClass {
813 #[inline]
814 fn drop(&mut self) {
815 unsafe {
816 gobject_ffi::g_type_class_unref(self.0.as_ptr() as *mut _);
817 }
818 }
819}
820
821impl Clone for FlagsClass {
822 #[inline]
823 fn clone(&self) -> Self {
824 unsafe {
825 Self(ptr::NonNull::new(gobject_ffi::g_type_class_ref(self.type_().into_glib()) as *mut _).unwrap())
826 }
827 }
828}
829
830#[derive(Debug)]
831pub struct ParseFlagsError(String);
832
833impl std::error::Error for ParseFlagsError {}
834
835impl fmt::Display for ParseFlagsError {
836 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
837 write!(f, "Unknown flag: '{}'", self.0)
838 }
839}
840
841impl ParseFlagsError {
842 pub fn flag(&self) -> &str {
843 &self.0
844 }
845}
846
847#[doc(alias = "GFlagsValue")]
853#[derive(Copy, Clone)]
854#[repr(transparent)]
855pub struct FlagsValue(gobject_ffi::GFlagsValue);
856
857unsafe impl Send for FlagsValue {}
858unsafe impl Sync for FlagsValue {}
859
860impl fmt::Debug for FlagsValue {
861 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
862 f.debug_struct("FlagsValue")
863 .field("value", &self.value())
864 .field("name", &self.name())
865 .field("nick", &self.nick())
866 .finish()
867 }
868}
869
870impl FlagsValue {
871 pub const unsafe fn unsafe_from(g_value: gobject_ffi::GFlagsValue) -> Self {
877 Self(g_value)
878 }
879
880 #[doc(alias = "get_value")]
883 pub fn value(&self) -> u32 {
884 self.0.value
885 }
886
887 #[doc(alias = "get_name")]
890 pub fn name(&self) -> &str {
891 unsafe { CStr::from_ptr(self.0.value_name).to_str().unwrap() }
892 }
893
894 #[doc(alias = "get_nick")]
897 pub fn nick(&self) -> &str {
898 unsafe { CStr::from_ptr(self.0.value_nick).to_str().unwrap() }
899 }
900
901 pub fn to_value(&self, flags: &FlagsClass) -> Value {
904 unsafe {
905 let mut v = Value::from_type_unchecked(flags.type_());
906 gobject_ffi::g_value_set_flags(v.to_glib_none_mut().0, self.0.value);
907 v
908 }
909 }
910
911 pub fn from_value(value: &Value) -> Option<(FlagsClass, Vec<&FlagsValue>)> {
914 unsafe {
915 let flags_class = FlagsClass::with_type(value.type_())?;
916 let mut res = Vec::new();
917 let f = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
918 for v in flags_class.values() {
919 if v.value() & f != 0 {
920 res.push(&*(v as *const FlagsValue));
921 }
922 }
923 Some((flags_class, res))
924 }
925 }
926}
927
928impl PartialEq for FlagsValue {
929 fn eq(&self, other: &Self) -> bool {
930 self.value().eq(&other.value())
931 }
932}
933
934impl Eq for FlagsValue {}
935
936impl UnsafeFrom<gobject_ffi::GFlagsValue> for FlagsValue {
937 unsafe fn unsafe_from(g_value: gobject_ffi::GFlagsValue) -> Self {
938 unsafe { Self::unsafe_from(g_value) }
939 }
940}
941
942impl EnumerationValue<FlagsValue> for FlagsValue {
945 type GlibType = gobject_ffi::GFlagsValue;
946 const ZERO: FlagsValue = unsafe {
947 FlagsValue::unsafe_from(gobject_ffi::GFlagsValue {
948 value: 0,
949 value_name: ptr::null(),
950 value_nick: ptr::null(),
951 })
952 };
953}
954
955pub type FlagsValuesStorage<const N: usize> = EnumerationValuesStorage<FlagsValue, N>;
958
959pub type FlagsValues = EnumerationValues<FlagsValue>;
962
963#[must_use = "The builder must be built to be used"]
982pub struct FlagsBuilder<'a>(&'a FlagsClass, Option<Value>);
983impl FlagsBuilder<'_> {
984 fn new(flags_class: &FlagsClass) -> FlagsBuilder<'_> {
985 let value = unsafe { Value::from_type_unchecked(flags_class.type_()) };
986 FlagsBuilder(flags_class, Some(value))
987 }
988
989 fn with_value(flags_class: &FlagsClass, value: Value) -> FlagsBuilder<'_> {
990 FlagsBuilder(flags_class, Some(value))
991 }
992
993 pub fn set(mut self, f: u32) -> Self {
996 if let Some(value) = self.1.take() {
997 self.1 = self.0.set(value, f).ok();
998 }
999
1000 self
1001 }
1002
1003 pub fn set_by_name(mut self, name: &str) -> Self {
1006 if let Some(value) = self.1.take() {
1007 self.1 = self.0.set_by_name(value, name).ok();
1008 }
1009
1010 self
1011 }
1012
1013 pub fn set_by_nick(mut self, nick: &str) -> Self {
1016 if let Some(value) = self.1.take() {
1017 self.1 = self.0.set_by_nick(value, nick).ok();
1018 }
1019
1020 self
1021 }
1022
1023 pub fn unset(mut self, f: u32) -> Self {
1026 if let Some(value) = self.1.take() {
1027 self.1 = self.0.unset(value, f).ok();
1028 }
1029
1030 self
1031 }
1032
1033 pub fn unset_by_name(mut self, name: &str) -> Self {
1036 if let Some(value) = self.1.take() {
1037 self.1 = self.0.unset_by_name(value, name).ok();
1038 }
1039
1040 self
1041 }
1042
1043 pub fn unset_by_nick(mut self, nick: &str) -> Self {
1046 if let Some(value) = self.1.take() {
1047 self.1 = self.0.unset_by_nick(value, nick).ok();
1048 }
1049
1050 self
1051 }
1052
1053 #[must_use = "Value returned from the builder should probably be used"]
1056 pub fn build(self) -> Option<Value> {
1057 self.1
1058 }
1059}
1060
1061unsafe impl<'a> crate::value::FromValue<'a> for Vec<&FlagsValue> {
1062 type Checker = FlagsTypeChecker;
1063
1064 unsafe fn from_value(value: &'a Value) -> Self {
1065 unsafe {
1066 let (_, v) = FlagsValue::from_value(value).unwrap();
1067 std::mem::transmute(v)
1069 }
1070 }
1071}
1072
1073pub struct FlagsTypeChecker();
1074unsafe impl crate::value::ValueTypeChecker for FlagsTypeChecker {
1075 type Error = InvalidFlagsError;
1076
1077 fn check(value: &Value) -> Result<(), Self::Error> {
1078 let t = value.type_();
1079 if t.is_a(Type::FLAGS) {
1080 Ok(())
1081 } else {
1082 Err(InvalidFlagsError)
1083 }
1084 }
1085}
1086
1087#[derive(Clone, PartialEq, Eq, Debug)]
1091pub struct InvalidFlagsError;
1092
1093impl fmt::Display for InvalidFlagsError {
1094 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1095 write!(f, "Value is not a flags")
1096 }
1097}
1098
1099impl std::error::Error for InvalidFlagsError {}
1100
1101pub trait EnumerationValue<E>: Copy {
1104 type GlibType;
1105 const ZERO: E;
1106}
1107
1108#[repr(C)]
1119pub struct EnumerationValuesStorage<E: EnumerationValue<E>, const S: usize>([E; S]);
1120
1121impl<E: EnumerationValue<E>, const S: usize> EnumerationValuesStorage<E, S> {
1122 pub const fn new<const N: usize>(values: [E; N]) -> Self {
1125 #[repr(C)]
1126 #[derive(Copy, Clone)]
1127 struct Both<E: Copy, const N: usize>([E; N], [E; 1]);
1128
1129 #[repr(C)]
1130 union Transmute<E: Copy, const N: usize, const S: usize> {
1131 from: Both<E, N>,
1132 to: [E; S],
1133 }
1134
1135 unsafe {
1137 let all = Transmute {
1139 from: Both(values, [E::ZERO; 1]),
1140 }
1141 .to;
1142 Self(all)
1143 }
1144 }
1145}
1146
1147impl<E: EnumerationValue<E>, const S: usize> AsRef<EnumerationValues<E>>
1148 for EnumerationValuesStorage<E, S>
1149{
1150 fn as_ref(&self) -> &EnumerationValues<E> {
1151 unsafe { &*(&self.0 as *const [E] as *const EnumerationValues<E>) }
1153 }
1154}
1155
1156#[repr(C)]
1167pub struct EnumerationValues<E: EnumerationValue<E>>([E]);
1168
1169impl<E: EnumerationValue<E>> Deref for EnumerationValues<E> {
1170 type Target = [E];
1171
1172 fn deref(&self) -> &Self::Target {
1175 unsafe { std::slice::from_raw_parts(self.0.as_ptr(), self.0.len() - 1) }
1177 }
1178}
1179
1180#[doc(hidden)]
1181impl<'a, E: 'a + EnumerationValue<E>> ToGlibPtr<'a, *const E::GlibType> for EnumerationValues<E> {
1182 type Storage = &'a Self;
1183
1184 fn to_glib_none(&'a self) -> Stash<'a, *const E::GlibType, Self> {
1185 Stash(self.0.as_ptr() as *const E::GlibType, self)
1186 }
1187}
1188
1189#[cfg(test)]
1190mod tests {
1191 use super::*;
1192
1193 #[test]
1194 fn test_flags() {
1195 let flags = FlagsClass::new::<crate::BindingFlags>();
1196 let values = flags.values();
1197 let def1 = values
1198 .iter()
1199 .find(|v| v.name() == "G_BINDING_DEFAULT")
1200 .unwrap();
1201 let def2 = flags.value_by_name("G_BINDING_DEFAULT").unwrap();
1202 assert!(ptr::eq(def1, def2));
1203
1204 let value = flags.to_value(0).unwrap();
1205 let values = value.get::<Vec<&FlagsValue>>().unwrap();
1206 assert_eq!(values.len(), 0);
1207
1208 assert_eq!(def1.value(), crate::BindingFlags::DEFAULT.bits());
1209 }
1210}