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)]
11pub enum UserDirectory {
12 #[doc(alias = "G_USER_DIRECTORY_DESKTOP")]
13 Desktop,
14 #[doc(alias = "G_USER_DIRECTORY_DOCUMENTS")]
15 Documents,
16 #[doc(alias = "G_USER_DIRECTORY_DOWNLOAD")]
17 Downloads,
18 #[doc(alias = "G_USER_DIRECTORY_MUSIC")]
19 Music,
20 #[doc(alias = "G_USER_DIRECTORY_PICTURES")]
21 Pictures,
22 #[doc(alias = "G_USER_DIRECTORY_PUBLIC_SHARE")]
23 PublicShare,
24 #[doc(alias = "G_USER_DIRECTORY_TEMPLATES")]
25 Templates,
26 #[doc(alias = "G_USER_DIRECTORY_VIDEOS")]
27 Videos,
28}
29
30#[doc(hidden)]
31impl IntoGlib for UserDirectory {
32 type GlibType = ffi::GUserDirectory;
33
34 #[inline]
35 fn into_glib(self) -> ffi::GUserDirectory {
36 match self {
37 Self::Desktop => ffi::G_USER_DIRECTORY_DESKTOP,
38 Self::Documents => ffi::G_USER_DIRECTORY_DOCUMENTS,
39 Self::Downloads => ffi::G_USER_DIRECTORY_DOWNLOAD,
40 Self::Music => ffi::G_USER_DIRECTORY_MUSIC,
41 Self::Pictures => ffi::G_USER_DIRECTORY_PICTURES,
42 Self::PublicShare => ffi::G_USER_DIRECTORY_PUBLIC_SHARE,
43 Self::Templates => ffi::G_USER_DIRECTORY_TEMPLATES,
44 Self::Videos => ffi::G_USER_DIRECTORY_VIDEOS,
45 }
46 }
47}
48
49#[doc(alias = "GEnumClass")]
53#[repr(transparent)]
54pub struct EnumClass(ptr::NonNull<gobject_ffi::GEnumClass>);
55
56unsafe impl Send for EnumClass {}
57unsafe impl Sync for EnumClass {}
58
59impl fmt::Debug for EnumClass {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 f.debug_struct("EnumClass")
62 .field("type", &self.type_())
63 .field("values", &self.values())
64 .finish()
65 }
66}
67
68impl EnumClass {
69 pub fn new<T: StaticType + HasParamSpec<ParamSpec = ParamSpecEnum>>() -> Self {
74 Self::with_type(T::static_type()).expect("invalid enum class")
75 }
76 pub fn with_type(type_: Type) -> Option<Self> {
81 unsafe {
82 let is_enum: bool = from_glib(gobject_ffi::g_type_is_a(
83 type_.into_glib(),
84 gobject_ffi::G_TYPE_ENUM,
85 ));
86 if !is_enum {
87 return None;
88 }
89
90 Some(EnumClass(
91 ptr::NonNull::new(gobject_ffi::g_type_class_ref(type_.into_glib()) as *mut _)
92 .unwrap(),
93 ))
94 }
95 }
96
97 pub fn type_(&self) -> Type {
100 unsafe { from_glib(self.0.as_ref().g_type_class.g_type) }
101 }
102
103 #[doc(alias = "g_enum_get_value")]
109 #[doc(alias = "get_value")]
110 pub fn value(&self, value: i32) -> Option<&EnumValue> {
111 unsafe {
112 let v = gobject_ffi::g_enum_get_value(self.0.as_ptr(), value);
113 if v.is_null() {
114 None
115 } else {
116 Some(&*(v as *const EnumValue))
117 }
118 }
119 }
120
121 #[doc(alias = "g_enum_get_value_by_name")]
127 #[doc(alias = "get_value_by_name")]
128 pub fn value_by_name(&self, name: &str) -> Option<&EnumValue> {
129 unsafe {
130 let v = gobject_ffi::g_enum_get_value_by_name(self.0.as_ptr(), name.to_glib_none().0);
131 if v.is_null() {
132 None
133 } else {
134 Some(&*(v as *const EnumValue))
135 }
136 }
137 }
138
139 #[doc(alias = "g_enum_get_value_by_nick")]
145 #[doc(alias = "get_value_by_nick")]
146 pub fn value_by_nick(&self, nick: &str) -> Option<&EnumValue> {
147 unsafe {
148 let v = gobject_ffi::g_enum_get_value_by_nick(self.0.as_ptr(), nick.to_glib_none().0);
149 if v.is_null() {
150 None
151 } else {
152 Some(&*(v as *const EnumValue))
153 }
154 }
155 }
156
157 #[doc(alias = "get_values")]
160 pub fn values(&self) -> &[EnumValue] {
161 unsafe {
162 if self.0.as_ref().n_values == 0 {
163 return &[];
164 }
165 std::slice::from_raw_parts(
166 self.0.as_ref().values as *const EnumValue,
167 self.0.as_ref().n_values as usize,
168 )
169 }
170 }
171
172 pub fn to_value(&self, value: i32) -> Option<Value> {
175 self.value(value).map(|v| v.to_value(self))
176 }
177
178 pub fn to_value_by_name(&self, name: &str) -> Option<Value> {
181 self.value_by_name(name).map(|v| v.to_value(self))
182 }
183
184 pub fn to_value_by_nick(&self, nick: &str) -> Option<Value> {
187 self.value_by_nick(nick).map(|v| v.to_value(self))
188 }
189
190 #[doc(alias = "g_enum_complete_type_info")]
200 pub fn complete_type_info(
201 type_: Type,
202 const_static_values: &'static EnumValues,
203 ) -> Option<TypeInfo> {
204 unsafe {
205 let is_enum: bool = from_glib(gobject_ffi::g_type_is_a(
206 type_.into_glib(),
207 gobject_ffi::G_TYPE_ENUM,
208 ));
209 if !is_enum {
210 return None;
211 }
212
213 let info = TypeInfo::default();
214 gobject_ffi::g_enum_complete_type_info(
215 type_.into_glib(),
216 info.as_ptr(),
217 const_static_values.to_glib_none().0,
218 );
219 Some(info)
220 }
221 }
222}
223
224impl Drop for EnumClass {
225 #[inline]
226 fn drop(&mut self) {
227 unsafe {
228 gobject_ffi::g_type_class_unref(self.0.as_ptr() as *mut _);
229 }
230 }
231}
232
233impl Clone for EnumClass {
234 #[inline]
235 fn clone(&self) -> Self {
236 unsafe {
237 Self(ptr::NonNull::new(gobject_ffi::g_type_class_ref(self.type_().into_glib()) as *mut _).unwrap())
238 }
239 }
240}
241
242#[doc(alias = "GEnumValue")]
245#[derive(Copy, Clone)]
246#[repr(transparent)]
247pub struct EnumValue(gobject_ffi::GEnumValue);
248
249unsafe impl Send for EnumValue {}
250unsafe impl Sync for EnumValue {}
251
252impl fmt::Debug for EnumValue {
253 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
254 f.debug_struct("EnumValue")
255 .field("value", &self.value())
256 .field("name", &self.name())
257 .field("nick", &self.nick())
258 .finish()
259 }
260}
261
262impl EnumValue {
263 pub const unsafe fn unsafe_from(g_value: gobject_ffi::GEnumValue) -> Self {
269 Self(g_value)
270 }
271
272 #[doc(alias = "get_value")]
275 pub fn value(&self) -> i32 {
276 self.0.value
277 }
278
279 #[doc(alias = "get_name")]
282 pub fn name<'a>(&self) -> &'a str {
283 unsafe { CStr::from_ptr(self.0.value_name).to_str().unwrap() }
284 }
285
286 #[doc(alias = "get_nick")]
289 pub fn nick<'a>(&self) -> &'a str {
290 unsafe { CStr::from_ptr(self.0.value_nick).to_str().unwrap() }
291 }
292
293 pub fn to_value(&self, enum_: &EnumClass) -> Value {
296 unsafe {
297 let mut v = Value::from_type_unchecked(enum_.type_());
298 gobject_ffi::g_value_set_enum(v.to_glib_none_mut().0, self.0.value);
299 v
300 }
301 }
302
303 pub fn from_value(value: &Value) -> Option<(EnumClass, &EnumValue)> {
306 unsafe {
307 let enum_class = EnumClass::with_type(value.type_())?;
308 let v = enum_class.value(gobject_ffi::g_value_get_enum(value.to_glib_none().0))?;
309 let v = &*(v as *const EnumValue);
310 Some((enum_class, v))
311 }
312 }
313}
314
315impl PartialEq for EnumValue {
316 fn eq(&self, other: &Self) -> bool {
317 self.value().eq(&other.value())
318 }
319}
320
321impl Eq for EnumValue {}
322
323impl PartialOrd for EnumValue {
324 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
325 Some(self.cmp(other))
326 }
327}
328
329impl Ord for EnumValue {
330 fn cmp(&self, other: &Self) -> cmp::Ordering {
331 self.value().cmp(&other.value())
332 }
333}
334
335impl UnsafeFrom<gobject_ffi::GEnumValue> for EnumValue {
336 unsafe fn unsafe_from(g_value: gobject_ffi::GEnumValue) -> Self {
337 unsafe { Self::unsafe_from(g_value) }
338 }
339}
340
341unsafe impl<'a> crate::value::FromValue<'a> for &EnumValue {
342 type Checker = EnumTypeChecker;
343
344 unsafe fn from_value(value: &'a Value) -> Self {
345 unsafe {
346 let (_, v) = EnumValue::from_value(value).unwrap();
347 std::mem::transmute(v)
349 }
350 }
351}
352
353impl EnumerationValue<EnumValue> for EnumValue {
356 type GlibType = gobject_ffi::GEnumValue;
357 const ZERO: EnumValue = unsafe {
358 EnumValue::unsafe_from(gobject_ffi::GEnumValue {
359 value: 0,
360 value_name: ptr::null(),
361 value_nick: ptr::null(),
362 })
363 };
364}
365
366pub type EnumValuesStorage<const N: usize> = EnumerationValuesStorage<EnumValue, N>;
369
370pub type EnumValues = EnumerationValues<EnumValue>;
373
374pub struct EnumTypeChecker();
375unsafe impl crate::value::ValueTypeChecker for EnumTypeChecker {
376 type Error = InvalidEnumError;
377
378 fn check(value: &Value) -> Result<(), Self::Error> {
379 let t = value.type_();
380 if t.is_a(Type::ENUM) {
381 Ok(())
382 } else {
383 Err(InvalidEnumError)
384 }
385 }
386}
387
388#[derive(Clone, PartialEq, Eq, Debug)]
392pub struct InvalidEnumError;
393
394impl fmt::Display for InvalidEnumError {
395 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
396 write!(f, "Value is not an enum")
397 }
398}
399
400impl std::error::Error for InvalidEnumError {}
401
402#[doc(alias = "GFlagsClass")]
406#[repr(transparent)]
407pub struct FlagsClass(ptr::NonNull<gobject_ffi::GFlagsClass>);
408
409unsafe impl Send for FlagsClass {}
410unsafe impl Sync for FlagsClass {}
411
412impl fmt::Debug for FlagsClass {
413 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
414 f.debug_struct("FlagsClass")
415 .field("type", &self.type_())
416 .field("values", &self.values())
417 .finish()
418 }
419}
420
421impl FlagsClass {
422 pub fn new<T: StaticType + HasParamSpec<ParamSpec = ParamSpecFlags>>() -> Self {
427 Self::with_type(T::static_type()).expect("invalid flags class")
428 }
429 pub fn with_type(type_: Type) -> Option<Self> {
434 unsafe {
435 let is_flags: bool = from_glib(gobject_ffi::g_type_is_a(
436 type_.into_glib(),
437 gobject_ffi::G_TYPE_FLAGS,
438 ));
439 if !is_flags {
440 return None;
441 }
442
443 Some(FlagsClass(
444 ptr::NonNull::new(gobject_ffi::g_type_class_ref(type_.into_glib()) as *mut _)
445 .unwrap(),
446 ))
447 }
448 }
449
450 pub fn type_(&self) -> Type {
453 unsafe { from_glib(self.0.as_ref().g_type_class.g_type) }
454 }
455
456 #[doc(alias = "g_flags_get_first_value")]
462 #[doc(alias = "get_value")]
463 pub fn value(&self, value: u32) -> Option<&FlagsValue> {
464 unsafe {
465 let v = gobject_ffi::g_flags_get_first_value(self.0.as_ptr(), value);
466 if v.is_null() {
467 None
468 } else {
469 Some(&*(v as *const FlagsValue))
470 }
471 }
472 }
473
474 #[doc(alias = "g_flags_get_value_by_name")]
480 #[doc(alias = "get_value_by_name")]
481 pub fn value_by_name(&self, name: &str) -> Option<&FlagsValue> {
482 unsafe {
483 let v = gobject_ffi::g_flags_get_value_by_name(self.0.as_ptr(), name.to_glib_none().0);
484 if v.is_null() {
485 None
486 } else {
487 Some(&*(v as *const FlagsValue))
488 }
489 }
490 }
491
492 #[doc(alias = "g_flags_get_value_by_nick")]
498 #[doc(alias = "get_value_by_nick")]
499 pub fn value_by_nick(&self, nick: &str) -> Option<&FlagsValue> {
500 unsafe {
501 let v = gobject_ffi::g_flags_get_value_by_nick(self.0.as_ptr(), nick.to_glib_none().0);
502 if v.is_null() {
503 None
504 } else {
505 Some(&*(v as *const FlagsValue))
506 }
507 }
508 }
509
510 #[doc(alias = "get_values")]
513 pub fn values(&self) -> &[FlagsValue] {
514 unsafe {
515 if self.0.as_ref().n_values == 0 {
516 return &[];
517 }
518 std::slice::from_raw_parts(
519 self.0.as_ref().values as *const FlagsValue,
520 self.0.as_ref().n_values as usize,
521 )
522 }
523 }
524
525 pub fn to_value(&self, value: u32) -> Option<Value> {
528 self.value(value).map(|v| v.to_value(self))
529 }
530
531 pub fn to_value_by_name(&self, name: &str) -> Option<Value> {
534 self.value_by_name(name).map(|v| v.to_value(self))
535 }
536
537 pub fn to_value_by_nick(&self, nick: &str) -> Option<Value> {
540 self.value_by_nick(nick).map(|v| v.to_value(self))
541 }
542
543 pub fn is_set(&self, value: &Value, f: u32) -> bool {
546 unsafe {
547 if self.type_() != value.type_() {
548 return false;
549 }
550
551 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
552 flags & f != 0
553 }
554 }
555
556 pub fn is_set_by_name(&self, value: &Value, name: &str) -> bool {
559 unsafe {
560 if self.type_() != value.type_() {
561 return false;
562 }
563
564 if let Some(f) = self.value_by_name(name) {
565 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
566 flags & f.value() != 0
567 } else {
568 false
569 }
570 }
571 }
572
573 pub fn is_set_by_nick(&self, value: &Value, nick: &str) -> bool {
576 unsafe {
577 if self.type_() != value.type_() {
578 return false;
579 }
580
581 if let Some(f) = self.value_by_nick(nick) {
582 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
583 flags & f.value() != 0
584 } else {
585 false
586 }
587 }
588 }
589
590 #[doc(alias = "g_value_set_flags")]
597 pub fn set(&self, mut value: Value, f: u32) -> Result<Value, Value> {
598 unsafe {
599 if self.type_() != value.type_() {
600 return Err(value);
601 }
602
603 if let Some(f) = self.value(f) {
604 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
605 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value());
606 Ok(value)
607 } else {
608 Err(value)
609 }
610 }
611 }
612
613 pub fn set_by_name(&self, mut value: Value, name: &str) -> Result<Value, Value> {
620 unsafe {
621 if self.type_() != value.type_() {
622 return Err(value);
623 }
624
625 if let Some(f) = self.value_by_name(name) {
626 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
627 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value());
628 Ok(value)
629 } else {
630 Err(value)
631 }
632 }
633 }
634
635 pub fn set_by_nick(&self, mut value: Value, nick: &str) -> Result<Value, Value> {
642 unsafe {
643 if self.type_() != value.type_() {
644 return Err(value);
645 }
646
647 if let Some(f) = self.value_by_nick(nick) {
648 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
649 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value());
650 Ok(value)
651 } else {
652 Err(value)
653 }
654 }
655 }
656
657 pub fn unset(&self, mut value: Value, f: u32) -> Result<Value, Value> {
664 unsafe {
665 if self.type_() != value.type_() {
666 return Err(value);
667 }
668
669 if let Some(f) = self.value(f) {
670 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
671 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value());
672 Ok(value)
673 } else {
674 Err(value)
675 }
676 }
677 }
678
679 pub fn unset_by_name(&self, mut value: Value, name: &str) -> Result<Value, Value> {
686 unsafe {
687 if self.type_() != value.type_() {
688 return Err(value);
689 }
690
691 if let Some(f) = self.value_by_name(name) {
692 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
693 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value());
694 Ok(value)
695 } else {
696 Err(value)
697 }
698 }
699 }
700
701 pub fn unset_by_nick(&self, mut value: Value, nick: &str) -> Result<Value, Value> {
708 unsafe {
709 if self.type_() != value.type_() {
710 return Err(value);
711 }
712
713 if let Some(f) = self.value_by_nick(nick) {
714 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
715 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value());
716 Ok(value)
717 } else {
718 Err(value)
719 }
720 }
721 }
722
723 pub fn to_nick_string(&self, mut value: u32) -> String {
726 let mut s = String::new();
727 for val in self.values() {
728 let v = val.value();
729 if v != 0 && (value & v) == v {
730 value &= !v;
731 if !s.is_empty() {
732 s.push('|');
733 }
734 s.push_str(val.nick());
735 }
736 }
737 s
738 }
739
740 pub fn from_nick_string(&self, s: &str) -> Result<u32, ParseFlagsError> {
743 s.split('|').try_fold(0u32, |acc, flag| {
744 self.value_by_nick(flag.trim())
745 .map(|v| acc + v.value())
746 .ok_or_else(|| ParseFlagsError(flag.to_owned()))
747 })
748 }
749
750 pub fn builder(&self) -> FlagsBuilder<'_> {
754 FlagsBuilder::new(self)
755 }
756
757 pub fn builder_with_value(&self, value: Value) -> Option<FlagsBuilder<'_>> {
761 if self.type_() != value.type_() {
762 return None;
763 }
764
765 Some(FlagsBuilder::with_value(self, value))
766 }
767
768 #[doc(alias = "g_flags_complete_type_info")]
778 pub fn complete_type_info(
779 type_: Type,
780 const_static_values: &'static FlagsValues,
781 ) -> Option<TypeInfo> {
782 unsafe {
783 let is_flags: bool = from_glib(gobject_ffi::g_type_is_a(
784 type_.into_glib(),
785 gobject_ffi::G_TYPE_FLAGS,
786 ));
787 if !is_flags {
788 return None;
789 }
790
791 let info = TypeInfo::default();
792 gobject_ffi::g_flags_complete_type_info(
793 type_.into_glib(),
794 info.as_ptr(),
795 const_static_values.to_glib_none().0,
796 );
797 Some(info)
798 }
799 }
800}
801
802impl Drop for FlagsClass {
803 #[inline]
804 fn drop(&mut self) {
805 unsafe {
806 gobject_ffi::g_type_class_unref(self.0.as_ptr() as *mut _);
807 }
808 }
809}
810
811impl Clone for FlagsClass {
812 #[inline]
813 fn clone(&self) -> Self {
814 unsafe {
815 Self(ptr::NonNull::new(gobject_ffi::g_type_class_ref(self.type_().into_glib()) as *mut _).unwrap())
816 }
817 }
818}
819
820#[derive(Debug)]
821pub struct ParseFlagsError(String);
822
823impl std::error::Error for ParseFlagsError {}
824
825impl fmt::Display for ParseFlagsError {
826 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
827 write!(f, "Unknown flag: '{}'", self.0)
828 }
829}
830
831impl ParseFlagsError {
832 pub fn flag(&self) -> &str {
833 &self.0
834 }
835}
836
837#[doc(alias = "GFlagsValue")]
840#[derive(Copy, Clone)]
841#[repr(transparent)]
842pub struct FlagsValue(gobject_ffi::GFlagsValue);
843
844unsafe impl Send for FlagsValue {}
845unsafe impl Sync for FlagsValue {}
846
847impl fmt::Debug for FlagsValue {
848 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
849 f.debug_struct("FlagsValue")
850 .field("value", &self.value())
851 .field("name", &self.name())
852 .field("nick", &self.nick())
853 .finish()
854 }
855}
856
857impl FlagsValue {
858 pub const unsafe fn unsafe_from(g_value: gobject_ffi::GFlagsValue) -> Self {
864 Self(g_value)
865 }
866
867 #[doc(alias = "get_value")]
870 pub fn value(&self) -> u32 {
871 self.0.value
872 }
873
874 #[doc(alias = "get_name")]
877 pub fn name<'a>(&self) -> &'a str {
878 unsafe { CStr::from_ptr(self.0.value_name).to_str().unwrap() }
879 }
880
881 #[doc(alias = "get_nick")]
884 pub fn nick<'a>(&self) -> &'a str {
885 unsafe { CStr::from_ptr(self.0.value_nick).to_str().unwrap() }
886 }
887
888 pub fn to_value(&self, flags: &FlagsClass) -> Value {
891 unsafe {
892 let mut v = Value::from_type_unchecked(flags.type_());
893 gobject_ffi::g_value_set_flags(v.to_glib_none_mut().0, self.0.value);
894 v
895 }
896 }
897
898 pub fn from_value(value: &Value) -> Option<(FlagsClass, Vec<&FlagsValue>)> {
901 unsafe {
902 let flags_class = FlagsClass::with_type(value.type_())?;
903 let mut res = Vec::new();
904 let f = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
905 for v in flags_class.values() {
906 if v.value() & f != 0 {
907 res.push(&*(v as *const FlagsValue));
908 }
909 }
910 Some((flags_class, res))
911 }
912 }
913}
914
915impl PartialEq for FlagsValue {
916 fn eq(&self, other: &Self) -> bool {
917 self.value().eq(&other.value())
918 }
919}
920
921impl Eq for FlagsValue {}
922
923impl UnsafeFrom<gobject_ffi::GFlagsValue> for FlagsValue {
924 unsafe fn unsafe_from(g_value: gobject_ffi::GFlagsValue) -> Self {
925 unsafe { Self::unsafe_from(g_value) }
926 }
927}
928
929impl EnumerationValue<FlagsValue> for FlagsValue {
932 type GlibType = gobject_ffi::GFlagsValue;
933 const ZERO: FlagsValue = unsafe {
934 FlagsValue::unsafe_from(gobject_ffi::GFlagsValue {
935 value: 0,
936 value_name: ptr::null(),
937 value_nick: ptr::null(),
938 })
939 };
940}
941
942pub type FlagsValuesStorage<const N: usize> = EnumerationValuesStorage<FlagsValue, N>;
945
946pub type FlagsValues = EnumerationValues<FlagsValue>;
949
950#[must_use = "The builder must be built to be used"]
969pub struct FlagsBuilder<'a>(&'a FlagsClass, Option<Value>);
970impl FlagsBuilder<'_> {
971 fn new(flags_class: &FlagsClass) -> FlagsBuilder<'_> {
972 let value = unsafe { Value::from_type_unchecked(flags_class.type_()) };
973 FlagsBuilder(flags_class, Some(value))
974 }
975
976 fn with_value(flags_class: &FlagsClass, value: Value) -> FlagsBuilder<'_> {
977 FlagsBuilder(flags_class, Some(value))
978 }
979
980 pub fn set(mut self, f: u32) -> Self {
983 if let Some(value) = self.1.take() {
984 self.1 = self.0.set(value, f).ok();
985 }
986
987 self
988 }
989
990 pub fn set_by_name(mut self, name: &str) -> Self {
993 if let Some(value) = self.1.take() {
994 self.1 = self.0.set_by_name(value, name).ok();
995 }
996
997 self
998 }
999
1000 pub fn set_by_nick(mut self, nick: &str) -> Self {
1003 if let Some(value) = self.1.take() {
1004 self.1 = self.0.set_by_nick(value, nick).ok();
1005 }
1006
1007 self
1008 }
1009
1010 pub fn unset(mut self, f: u32) -> Self {
1013 if let Some(value) = self.1.take() {
1014 self.1 = self.0.unset(value, f).ok();
1015 }
1016
1017 self
1018 }
1019
1020 pub fn unset_by_name(mut self, name: &str) -> Self {
1023 if let Some(value) = self.1.take() {
1024 self.1 = self.0.unset_by_name(value, name).ok();
1025 }
1026
1027 self
1028 }
1029
1030 pub fn unset_by_nick(mut self, nick: &str) -> Self {
1033 if let Some(value) = self.1.take() {
1034 self.1 = self.0.unset_by_nick(value, nick).ok();
1035 }
1036
1037 self
1038 }
1039
1040 #[must_use = "Value returned from the builder should probably be used"]
1043 pub fn build(self) -> Option<Value> {
1044 self.1
1045 }
1046}
1047
1048unsafe impl<'a> crate::value::FromValue<'a> for Vec<&FlagsValue> {
1049 type Checker = FlagsTypeChecker;
1050
1051 unsafe fn from_value(value: &'a Value) -> Self {
1052 unsafe {
1053 let (_, v) = FlagsValue::from_value(value).unwrap();
1054 std::mem::transmute(v)
1056 }
1057 }
1058}
1059
1060pub struct FlagsTypeChecker();
1061unsafe impl crate::value::ValueTypeChecker for FlagsTypeChecker {
1062 type Error = InvalidFlagsError;
1063
1064 fn check(value: &Value) -> Result<(), Self::Error> {
1065 let t = value.type_();
1066 if t.is_a(Type::FLAGS) {
1067 Ok(())
1068 } else {
1069 Err(InvalidFlagsError)
1070 }
1071 }
1072}
1073
1074#[derive(Clone, PartialEq, Eq, Debug)]
1078pub struct InvalidFlagsError;
1079
1080impl fmt::Display for InvalidFlagsError {
1081 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1082 write!(f, "Value is not a flags")
1083 }
1084}
1085
1086impl std::error::Error for InvalidFlagsError {}
1087
1088pub trait EnumerationValue<E>: Copy {
1091 type GlibType;
1092 const ZERO: E;
1093}
1094
1095#[repr(C)]
1106pub struct EnumerationValuesStorage<E: EnumerationValue<E>, const S: usize>([E; S]);
1107
1108impl<E: EnumerationValue<E>, const S: usize> EnumerationValuesStorage<E, S> {
1109 pub const fn new<const N: usize>(values: [E; N]) -> Self {
1112 #[repr(C)]
1113 #[derive(Copy, Clone)]
1114 struct Both<E: Copy, const N: usize>([E; N], [E; 1]);
1115
1116 #[repr(C)]
1117 union Transmute<E: Copy, const N: usize, const S: usize> {
1118 from: Both<E, N>,
1119 to: [E; S],
1120 }
1121
1122 unsafe {
1124 let all = Transmute {
1126 from: Both(values, [E::ZERO; 1]),
1127 }
1128 .to;
1129 Self(all)
1130 }
1131 }
1132}
1133
1134impl<E: EnumerationValue<E>, const S: usize> AsRef<EnumerationValues<E>>
1135 for EnumerationValuesStorage<E, S>
1136{
1137 fn as_ref(&self) -> &EnumerationValues<E> {
1138 unsafe { &*(&self.0 as *const [E] as *const EnumerationValues<E>) }
1140 }
1141}
1142
1143#[repr(C)]
1154pub struct EnumerationValues<E: EnumerationValue<E>>([E]);
1155
1156impl<E: EnumerationValue<E>> Deref for EnumerationValues<E> {
1157 type Target = [E];
1158
1159 fn deref(&self) -> &Self::Target {
1162 unsafe { std::slice::from_raw_parts(self.0.as_ptr(), self.0.len() - 1) }
1164 }
1165}
1166
1167#[doc(hidden)]
1168impl<'a, E: 'a + EnumerationValue<E>> ToGlibPtr<'a, *const E::GlibType> for EnumerationValues<E> {
1169 type Storage = &'a Self;
1170
1171 fn to_glib_none(&'a self) -> Stash<'a, *const E::GlibType, Self> {
1172 Stash(self.0.as_ptr() as *const E::GlibType, self)
1173 }
1174}
1175
1176#[cfg(test)]
1177mod tests {
1178 use super::*;
1179
1180 #[test]
1181 fn test_flags() {
1182 let flags = FlagsClass::new::<crate::BindingFlags>();
1183 let values = flags.values();
1184 let def1 = values
1185 .iter()
1186 .find(|v| v.name() == "G_BINDING_DEFAULT")
1187 .unwrap();
1188 let def2 = flags.value_by_name("G_BINDING_DEFAULT").unwrap();
1189 assert!(ptr::eq(def1, def2));
1190
1191 let value = flags.to_value(0).unwrap();
1192 let values = value.get::<Vec<&FlagsValue>>().unwrap();
1193 assert_eq!(values.len(), 0);
1194
1195 assert_eq!(def1.value(), crate::BindingFlags::DEFAULT.bits());
1196 }
1197}