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)]
26pub enum UserDirectory {
27 #[doc(alias = "G_USER_DIRECTORY_DESKTOP")]
28 Desktop,
29 #[doc(alias = "G_USER_DIRECTORY_DOCUMENTS")]
30 Documents,
31 #[doc(alias = "G_USER_DIRECTORY_DOWNLOAD")]
32 Downloads,
33 #[doc(alias = "G_USER_DIRECTORY_MUSIC")]
34 Music,
35 #[doc(alias = "G_USER_DIRECTORY_PICTURES")]
36 Pictures,
37 #[doc(alias = "G_USER_DIRECTORY_PUBLIC_SHARE")]
38 PublicShare,
39 #[doc(alias = "G_USER_DIRECTORY_TEMPLATES")]
40 Templates,
41 #[doc(alias = "G_USER_DIRECTORY_VIDEOS")]
42 Videos,
43}
44
45#[doc(hidden)]
46impl IntoGlib for UserDirectory {
47 type GlibType = ffi::GUserDirectory;
48
49 #[inline]
50 fn into_glib(self) -> ffi::GUserDirectory {
51 match self {
52 Self::Desktop => ffi::G_USER_DIRECTORY_DESKTOP,
53 Self::Documents => ffi::G_USER_DIRECTORY_DOCUMENTS,
54 Self::Downloads => ffi::G_USER_DIRECTORY_DOWNLOAD,
55 Self::Music => ffi::G_USER_DIRECTORY_MUSIC,
56 Self::Pictures => ffi::G_USER_DIRECTORY_PICTURES,
57 Self::PublicShare => ffi::G_USER_DIRECTORY_PUBLIC_SHARE,
58 Self::Templates => ffi::G_USER_DIRECTORY_TEMPLATES,
59 Self::Videos => ffi::G_USER_DIRECTORY_VIDEOS,
60 }
61 }
62}
63
64#[doc(alias = "GEnumClass")]
68#[repr(transparent)]
69pub struct EnumClass(ptr::NonNull<gobject_ffi::GEnumClass>);
70
71unsafe impl Send for EnumClass {}
72unsafe impl Sync for EnumClass {}
73
74impl fmt::Debug for EnumClass {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 f.debug_struct("EnumClass")
77 .field("type", &self.type_())
78 .field("values", &self.values())
79 .finish()
80 }
81}
82
83impl EnumClass {
84 pub fn new<T: StaticType + HasParamSpec<ParamSpec = ParamSpecEnum>>() -> Self {
89 Self::with_type(T::static_type()).expect("invalid enum class")
90 }
91 pub fn with_type(type_: Type) -> Option<Self> {
96 unsafe {
97 let is_enum: bool = from_glib(gobject_ffi::g_type_is_a(
98 type_.into_glib(),
99 gobject_ffi::G_TYPE_ENUM,
100 ));
101 if !is_enum {
102 return None;
103 }
104
105 Some(EnumClass(
106 ptr::NonNull::new(gobject_ffi::g_type_class_ref(type_.into_glib()) as *mut _)
107 .unwrap(),
108 ))
109 }
110 }
111
112 pub fn type_(&self) -> Type {
115 unsafe { from_glib(self.0.as_ref().g_type_class.g_type) }
116 }
117
118 #[doc(alias = "g_enum_get_value")]
124 #[doc(alias = "get_value")]
125 pub fn value(&self, value: i32) -> Option<&EnumValue> {
126 unsafe {
127 let v = gobject_ffi::g_enum_get_value(self.0.as_ptr(), value);
128 if v.is_null() {
129 None
130 } else {
131 Some(&*(v as *const EnumValue))
132 }
133 }
134 }
135
136 #[doc(alias = "g_enum_get_value_by_name")]
142 #[doc(alias = "get_value_by_name")]
143 pub fn value_by_name(&self, name: &str) -> Option<&EnumValue> {
144 unsafe {
145 let v = gobject_ffi::g_enum_get_value_by_name(self.0.as_ptr(), name.to_glib_none().0);
146 if v.is_null() {
147 None
148 } else {
149 Some(&*(v as *const EnumValue))
150 }
151 }
152 }
153
154 #[doc(alias = "g_enum_get_value_by_nick")]
160 #[doc(alias = "get_value_by_nick")]
161 pub fn value_by_nick(&self, nick: &str) -> Option<&EnumValue> {
162 unsafe {
163 let v = gobject_ffi::g_enum_get_value_by_nick(self.0.as_ptr(), nick.to_glib_none().0);
164 if v.is_null() {
165 None
166 } else {
167 Some(&*(v as *const EnumValue))
168 }
169 }
170 }
171
172 #[doc(alias = "get_values")]
175 pub fn values(&self) -> &[EnumValue] {
176 unsafe {
177 if self.0.as_ref().n_values == 0 {
178 return &[];
179 }
180 std::slice::from_raw_parts(
181 self.0.as_ref().values as *const EnumValue,
182 self.0.as_ref().n_values as usize,
183 )
184 }
185 }
186
187 pub fn to_value(&self, value: i32) -> Option<Value> {
190 self.value(value).map(|v| v.to_value(self))
191 }
192
193 pub fn to_value_by_name(&self, name: &str) -> Option<Value> {
196 self.value_by_name(name).map(|v| v.to_value(self))
197 }
198
199 pub fn to_value_by_nick(&self, nick: &str) -> Option<Value> {
202 self.value_by_nick(nick).map(|v| v.to_value(self))
203 }
204
205 #[doc(alias = "g_enum_complete_type_info")]
215 pub fn complete_type_info(
216 type_: Type,
217 const_static_values: &'static EnumValues,
218 ) -> Option<TypeInfo> {
219 unsafe {
220 let is_enum: bool = from_glib(gobject_ffi::g_type_is_a(
221 type_.into_glib(),
222 gobject_ffi::G_TYPE_ENUM,
223 ));
224 if !is_enum {
225 return None;
226 }
227
228 let info = TypeInfo::default();
229 gobject_ffi::g_enum_complete_type_info(
230 type_.into_glib(),
231 info.as_ptr(),
232 const_static_values.to_glib_none().0,
233 );
234 Some(info)
235 }
236 }
237}
238
239impl Drop for EnumClass {
240 #[inline]
241 fn drop(&mut self) {
242 unsafe {
243 gobject_ffi::g_type_class_unref(self.0.as_ptr() as *mut _);
244 }
245 }
246}
247
248impl Clone for EnumClass {
249 #[inline]
250 fn clone(&self) -> Self {
251 unsafe {
252 Self(ptr::NonNull::new(gobject_ffi::g_type_class_ref(self.type_().into_glib()) as *mut _).unwrap())
253 }
254 }
255}
256
257#[doc(alias = "GEnumValue")]
266#[derive(Copy, Clone)]
267#[repr(transparent)]
268pub struct EnumValue(gobject_ffi::GEnumValue);
269
270unsafe impl Send for EnumValue {}
271unsafe impl Sync for EnumValue {}
272
273impl fmt::Debug for EnumValue {
274 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
275 f.debug_struct("EnumValue")
276 .field("value", &self.value())
277 .field("name", &self.name())
278 .field("nick", &self.nick())
279 .finish()
280 }
281}
282
283impl EnumValue {
284 pub const unsafe fn unsafe_from(g_value: gobject_ffi::GEnumValue) -> Self {
290 Self(g_value)
291 }
292
293 #[doc(alias = "get_value")]
296 pub fn value(&self) -> i32 {
297 self.0.value
298 }
299
300 #[doc(alias = "get_name")]
303 pub fn name<'a>(&self) -> &'a str {
304 unsafe { CStr::from_ptr(self.0.value_name).to_str().unwrap() }
305 }
306
307 #[doc(alias = "get_nick")]
310 pub fn nick<'a>(&self) -> &'a str {
311 unsafe { CStr::from_ptr(self.0.value_nick).to_str().unwrap() }
312 }
313
314 pub fn to_value(&self, enum_: &EnumClass) -> Value {
317 unsafe {
318 let mut v = Value::from_type_unchecked(enum_.type_());
319 gobject_ffi::g_value_set_enum(v.to_glib_none_mut().0, self.0.value);
320 v
321 }
322 }
323
324 pub fn from_value(value: &Value) -> Option<(EnumClass, &EnumValue)> {
327 unsafe {
328 let enum_class = EnumClass::with_type(value.type_())?;
329 let v = enum_class.value(gobject_ffi::g_value_get_enum(value.to_glib_none().0))?;
330 let v = &*(v as *const EnumValue);
331 Some((enum_class, v))
332 }
333 }
334}
335
336impl PartialEq for EnumValue {
337 fn eq(&self, other: &Self) -> bool {
338 self.value().eq(&other.value())
339 }
340}
341
342impl Eq for EnumValue {}
343
344impl PartialOrd for EnumValue {
345 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
346 Some(self.cmp(other))
347 }
348}
349
350impl Ord for EnumValue {
351 fn cmp(&self, other: &Self) -> cmp::Ordering {
352 self.value().cmp(&other.value())
353 }
354}
355
356impl UnsafeFrom<gobject_ffi::GEnumValue> for EnumValue {
357 unsafe fn unsafe_from(g_value: gobject_ffi::GEnumValue) -> Self {
358 unsafe { Self::unsafe_from(g_value) }
359 }
360}
361
362unsafe impl<'a> crate::value::FromValue<'a> for &EnumValue {
363 type Checker = EnumTypeChecker;
364
365 unsafe fn from_value(value: &'a Value) -> Self {
366 unsafe {
367 let (_, v) = EnumValue::from_value(value).unwrap();
368 std::mem::transmute(v)
370 }
371 }
372}
373
374impl EnumerationValue<EnumValue> for EnumValue {
377 type GlibType = gobject_ffi::GEnumValue;
378 const ZERO: EnumValue = unsafe {
379 EnumValue::unsafe_from(gobject_ffi::GEnumValue {
380 value: 0,
381 value_name: ptr::null(),
382 value_nick: ptr::null(),
383 })
384 };
385}
386
387pub type EnumValuesStorage<const N: usize> = EnumerationValuesStorage<EnumValue, N>;
390
391pub type EnumValues = EnumerationValues<EnumValue>;
394
395pub struct EnumTypeChecker();
396unsafe impl crate::value::ValueTypeChecker for EnumTypeChecker {
397 type Error = InvalidEnumError;
398
399 fn check(value: &Value) -> Result<(), Self::Error> {
400 let t = value.type_();
401 if t.is_a(Type::ENUM) {
402 Ok(())
403 } else {
404 Err(InvalidEnumError)
405 }
406 }
407}
408
409#[derive(Clone, PartialEq, Eq, Debug)]
413pub struct InvalidEnumError;
414
415impl fmt::Display for InvalidEnumError {
416 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
417 write!(f, "Value is not an enum")
418 }
419}
420
421impl std::error::Error for InvalidEnumError {}
422
423#[doc(alias = "GFlagsClass")]
427#[repr(transparent)]
428pub struct FlagsClass(ptr::NonNull<gobject_ffi::GFlagsClass>);
429
430unsafe impl Send for FlagsClass {}
431unsafe impl Sync for FlagsClass {}
432
433impl fmt::Debug for FlagsClass {
434 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
435 f.debug_struct("FlagsClass")
436 .field("type", &self.type_())
437 .field("values", &self.values())
438 .finish()
439 }
440}
441
442impl FlagsClass {
443 pub fn new<T: StaticType + HasParamSpec<ParamSpec = ParamSpecFlags>>() -> Self {
448 Self::with_type(T::static_type()).expect("invalid flags class")
449 }
450 pub fn with_type(type_: Type) -> Option<Self> {
455 unsafe {
456 let is_flags: bool = from_glib(gobject_ffi::g_type_is_a(
457 type_.into_glib(),
458 gobject_ffi::G_TYPE_FLAGS,
459 ));
460 if !is_flags {
461 return None;
462 }
463
464 Some(FlagsClass(
465 ptr::NonNull::new(gobject_ffi::g_type_class_ref(type_.into_glib()) as *mut _)
466 .unwrap(),
467 ))
468 }
469 }
470
471 pub fn type_(&self) -> Type {
474 unsafe { from_glib(self.0.as_ref().g_type_class.g_type) }
475 }
476
477 #[doc(alias = "g_flags_get_first_value")]
483 #[doc(alias = "get_value")]
484 pub fn value(&self, value: u32) -> Option<&FlagsValue> {
485 unsafe {
486 let v = gobject_ffi::g_flags_get_first_value(self.0.as_ptr(), value);
487 if v.is_null() {
488 None
489 } else {
490 Some(&*(v as *const FlagsValue))
491 }
492 }
493 }
494
495 #[doc(alias = "g_flags_get_value_by_name")]
501 #[doc(alias = "get_value_by_name")]
502 pub fn value_by_name(&self, name: &str) -> Option<&FlagsValue> {
503 unsafe {
504 let v = gobject_ffi::g_flags_get_value_by_name(self.0.as_ptr(), name.to_glib_none().0);
505 if v.is_null() {
506 None
507 } else {
508 Some(&*(v as *const FlagsValue))
509 }
510 }
511 }
512
513 #[doc(alias = "g_flags_get_value_by_nick")]
519 #[doc(alias = "get_value_by_nick")]
520 pub fn value_by_nick(&self, nick: &str) -> Option<&FlagsValue> {
521 unsafe {
522 let v = gobject_ffi::g_flags_get_value_by_nick(self.0.as_ptr(), nick.to_glib_none().0);
523 if v.is_null() {
524 None
525 } else {
526 Some(&*(v as *const FlagsValue))
527 }
528 }
529 }
530
531 #[doc(alias = "get_values")]
534 pub fn values(&self) -> &[FlagsValue] {
535 unsafe {
536 if self.0.as_ref().n_values == 0 {
537 return &[];
538 }
539 std::slice::from_raw_parts(
540 self.0.as_ref().values as *const FlagsValue,
541 self.0.as_ref().n_values as usize,
542 )
543 }
544 }
545
546 pub fn to_value(&self, value: u32) -> Option<Value> {
549 self.value(value).map(|v| v.to_value(self))
550 }
551
552 pub fn to_value_by_name(&self, name: &str) -> Option<Value> {
555 self.value_by_name(name).map(|v| v.to_value(self))
556 }
557
558 pub fn to_value_by_nick(&self, nick: &str) -> Option<Value> {
561 self.value_by_nick(nick).map(|v| v.to_value(self))
562 }
563
564 pub fn is_set(&self, value: &Value, f: u32) -> bool {
567 unsafe {
568 if self.type_() != value.type_() {
569 return false;
570 }
571
572 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
573 flags & f != 0
574 }
575 }
576
577 pub fn is_set_by_name(&self, value: &Value, name: &str) -> bool {
580 unsafe {
581 if self.type_() != value.type_() {
582 return false;
583 }
584
585 if let Some(f) = self.value_by_name(name) {
586 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
587 flags & f.value() != 0
588 } else {
589 false
590 }
591 }
592 }
593
594 pub fn is_set_by_nick(&self, value: &Value, nick: &str) -> bool {
597 unsafe {
598 if self.type_() != value.type_() {
599 return false;
600 }
601
602 if let Some(f) = self.value_by_nick(nick) {
603 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
604 flags & f.value() != 0
605 } else {
606 false
607 }
608 }
609 }
610
611 #[doc(alias = "g_value_set_flags")]
618 pub fn set(&self, mut value: Value, f: u32) -> Result<Value, Value> {
619 unsafe {
620 if self.type_() != value.type_() {
621 return Err(value);
622 }
623
624 if let Some(f) = self.value(f) {
625 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
626 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value());
627 Ok(value)
628 } else {
629 Err(value)
630 }
631 }
632 }
633
634 pub fn set_by_name(&self, mut value: Value, name: &str) -> Result<Value, Value> {
641 unsafe {
642 if self.type_() != value.type_() {
643 return Err(value);
644 }
645
646 if let Some(f) = self.value_by_name(name) {
647 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
648 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value());
649 Ok(value)
650 } else {
651 Err(value)
652 }
653 }
654 }
655
656 pub fn set_by_nick(&self, mut value: Value, nick: &str) -> Result<Value, Value> {
663 unsafe {
664 if self.type_() != value.type_() {
665 return Err(value);
666 }
667
668 if let Some(f) = self.value_by_nick(nick) {
669 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
670 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value());
671 Ok(value)
672 } else {
673 Err(value)
674 }
675 }
676 }
677
678 pub fn unset(&self, mut value: Value, f: u32) -> Result<Value, Value> {
685 unsafe {
686 if self.type_() != value.type_() {
687 return Err(value);
688 }
689
690 if let Some(f) = self.value(f) {
691 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
692 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value());
693 Ok(value)
694 } else {
695 Err(value)
696 }
697 }
698 }
699
700 pub fn unset_by_name(&self, mut value: Value, name: &str) -> Result<Value, Value> {
707 unsafe {
708 if self.type_() != value.type_() {
709 return Err(value);
710 }
711
712 if let Some(f) = self.value_by_name(name) {
713 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
714 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value());
715 Ok(value)
716 } else {
717 Err(value)
718 }
719 }
720 }
721
722 pub fn unset_by_nick(&self, mut value: Value, nick: &str) -> Result<Value, Value> {
729 unsafe {
730 if self.type_() != value.type_() {
731 return Err(value);
732 }
733
734 if let Some(f) = self.value_by_nick(nick) {
735 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
736 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value());
737 Ok(value)
738 } else {
739 Err(value)
740 }
741 }
742 }
743
744 pub fn to_nick_string(&self, mut value: u32) -> String {
747 let mut s = String::new();
748 for val in self.values() {
749 let v = val.value();
750 if v != 0 && (value & v) == v {
751 value &= !v;
752 if !s.is_empty() {
753 s.push('|');
754 }
755 s.push_str(val.nick());
756 }
757 }
758 s
759 }
760
761 pub fn from_nick_string(&self, s: &str) -> Result<u32, ParseFlagsError> {
764 s.split('|').try_fold(0u32, |acc, flag| {
765 self.value_by_nick(flag.trim())
766 .map(|v| acc + v.value())
767 .ok_or_else(|| ParseFlagsError(flag.to_owned()))
768 })
769 }
770
771 pub fn builder(&self) -> FlagsBuilder<'_> {
775 FlagsBuilder::new(self)
776 }
777
778 pub fn builder_with_value(&self, value: Value) -> Option<FlagsBuilder<'_>> {
782 if self.type_() != value.type_() {
783 return None;
784 }
785
786 Some(FlagsBuilder::with_value(self, value))
787 }
788
789 #[doc(alias = "g_flags_complete_type_info")]
799 pub fn complete_type_info(
800 type_: Type,
801 const_static_values: &'static FlagsValues,
802 ) -> Option<TypeInfo> {
803 unsafe {
804 let is_flags: bool = from_glib(gobject_ffi::g_type_is_a(
805 type_.into_glib(),
806 gobject_ffi::G_TYPE_FLAGS,
807 ));
808 if !is_flags {
809 return None;
810 }
811
812 let info = TypeInfo::default();
813 gobject_ffi::g_flags_complete_type_info(
814 type_.into_glib(),
815 info.as_ptr(),
816 const_static_values.to_glib_none().0,
817 );
818 Some(info)
819 }
820 }
821}
822
823impl Drop for FlagsClass {
824 #[inline]
825 fn drop(&mut self) {
826 unsafe {
827 gobject_ffi::g_type_class_unref(self.0.as_ptr() as *mut _);
828 }
829 }
830}
831
832impl Clone for FlagsClass {
833 #[inline]
834 fn clone(&self) -> Self {
835 unsafe {
836 Self(ptr::NonNull::new(gobject_ffi::g_type_class_ref(self.type_().into_glib()) as *mut _).unwrap())
837 }
838 }
839}
840
841#[derive(Debug)]
842pub struct ParseFlagsError(String);
843
844impl std::error::Error for ParseFlagsError {}
845
846impl fmt::Display for ParseFlagsError {
847 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
848 write!(f, "Unknown flag: '{}'", self.0)
849 }
850}
851
852impl ParseFlagsError {
853 pub fn flag(&self) -> &str {
854 &self.0
855 }
856}
857
858#[doc(alias = "GFlagsValue")]
867#[derive(Copy, Clone)]
868#[repr(transparent)]
869pub struct FlagsValue(gobject_ffi::GFlagsValue);
870
871unsafe impl Send for FlagsValue {}
872unsafe impl Sync for FlagsValue {}
873
874impl fmt::Debug for FlagsValue {
875 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
876 f.debug_struct("FlagsValue")
877 .field("value", &self.value())
878 .field("name", &self.name())
879 .field("nick", &self.nick())
880 .finish()
881 }
882}
883
884impl FlagsValue {
885 pub const unsafe fn unsafe_from(g_value: gobject_ffi::GFlagsValue) -> Self {
891 Self(g_value)
892 }
893
894 #[doc(alias = "get_value")]
897 pub fn value(&self) -> u32 {
898 self.0.value
899 }
900
901 #[doc(alias = "get_name")]
904 pub fn name<'a>(&self) -> &'a str {
905 unsafe { CStr::from_ptr(self.0.value_name).to_str().unwrap() }
906 }
907
908 #[doc(alias = "get_nick")]
911 pub fn nick<'a>(&self) -> &'a str {
912 unsafe { CStr::from_ptr(self.0.value_nick).to_str().unwrap() }
913 }
914
915 pub fn to_value(&self, flags: &FlagsClass) -> Value {
918 unsafe {
919 let mut v = Value::from_type_unchecked(flags.type_());
920 gobject_ffi::g_value_set_flags(v.to_glib_none_mut().0, self.0.value);
921 v
922 }
923 }
924
925 pub fn from_value(value: &Value) -> Option<(FlagsClass, Vec<&FlagsValue>)> {
928 unsafe {
929 let flags_class = FlagsClass::with_type(value.type_())?;
930 let mut res = Vec::new();
931 let f = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
932 for v in flags_class.values() {
933 if v.value() & f != 0 {
934 res.push(&*(v as *const FlagsValue));
935 }
936 }
937 Some((flags_class, res))
938 }
939 }
940}
941
942impl PartialEq for FlagsValue {
943 fn eq(&self, other: &Self) -> bool {
944 self.value().eq(&other.value())
945 }
946}
947
948impl Eq for FlagsValue {}
949
950impl UnsafeFrom<gobject_ffi::GFlagsValue> for FlagsValue {
951 unsafe fn unsafe_from(g_value: gobject_ffi::GFlagsValue) -> Self {
952 unsafe { Self::unsafe_from(g_value) }
953 }
954}
955
956impl EnumerationValue<FlagsValue> for FlagsValue {
959 type GlibType = gobject_ffi::GFlagsValue;
960 const ZERO: FlagsValue = unsafe {
961 FlagsValue::unsafe_from(gobject_ffi::GFlagsValue {
962 value: 0,
963 value_name: ptr::null(),
964 value_nick: ptr::null(),
965 })
966 };
967}
968
969pub type FlagsValuesStorage<const N: usize> = EnumerationValuesStorage<FlagsValue, N>;
972
973pub type FlagsValues = EnumerationValues<FlagsValue>;
976
977#[must_use = "The builder must be built to be used"]
996pub struct FlagsBuilder<'a>(&'a FlagsClass, Option<Value>);
997impl FlagsBuilder<'_> {
998 fn new(flags_class: &FlagsClass) -> FlagsBuilder<'_> {
999 let value = unsafe { Value::from_type_unchecked(flags_class.type_()) };
1000 FlagsBuilder(flags_class, Some(value))
1001 }
1002
1003 fn with_value(flags_class: &FlagsClass, value: Value) -> FlagsBuilder<'_> {
1004 FlagsBuilder(flags_class, Some(value))
1005 }
1006
1007 pub fn set(mut self, f: u32) -> Self {
1010 if let Some(value) = self.1.take() {
1011 self.1 = self.0.set(value, f).ok();
1012 }
1013
1014 self
1015 }
1016
1017 pub fn set_by_name(mut self, name: &str) -> Self {
1020 if let Some(value) = self.1.take() {
1021 self.1 = self.0.set_by_name(value, name).ok();
1022 }
1023
1024 self
1025 }
1026
1027 pub fn set_by_nick(mut self, nick: &str) -> Self {
1030 if let Some(value) = self.1.take() {
1031 self.1 = self.0.set_by_nick(value, nick).ok();
1032 }
1033
1034 self
1035 }
1036
1037 pub fn unset(mut self, f: u32) -> Self {
1040 if let Some(value) = self.1.take() {
1041 self.1 = self.0.unset(value, f).ok();
1042 }
1043
1044 self
1045 }
1046
1047 pub fn unset_by_name(mut self, name: &str) -> Self {
1050 if let Some(value) = self.1.take() {
1051 self.1 = self.0.unset_by_name(value, name).ok();
1052 }
1053
1054 self
1055 }
1056
1057 pub fn unset_by_nick(mut self, nick: &str) -> Self {
1060 if let Some(value) = self.1.take() {
1061 self.1 = self.0.unset_by_nick(value, nick).ok();
1062 }
1063
1064 self
1065 }
1066
1067 #[must_use = "Value returned from the builder should probably be used"]
1070 pub fn build(self) -> Option<Value> {
1071 self.1
1072 }
1073}
1074
1075unsafe impl<'a> crate::value::FromValue<'a> for Vec<&FlagsValue> {
1076 type Checker = FlagsTypeChecker;
1077
1078 unsafe fn from_value(value: &'a Value) -> Self {
1079 unsafe {
1080 let (_, v) = FlagsValue::from_value(value).unwrap();
1081 std::mem::transmute(v)
1083 }
1084 }
1085}
1086
1087pub struct FlagsTypeChecker();
1088unsafe impl crate::value::ValueTypeChecker for FlagsTypeChecker {
1089 type Error = InvalidFlagsError;
1090
1091 fn check(value: &Value) -> Result<(), Self::Error> {
1092 let t = value.type_();
1093 if t.is_a(Type::FLAGS) {
1094 Ok(())
1095 } else {
1096 Err(InvalidFlagsError)
1097 }
1098 }
1099}
1100
1101#[derive(Clone, PartialEq, Eq, Debug)]
1105pub struct InvalidFlagsError;
1106
1107impl fmt::Display for InvalidFlagsError {
1108 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1109 write!(f, "Value is not a flags")
1110 }
1111}
1112
1113impl std::error::Error for InvalidFlagsError {}
1114
1115pub trait EnumerationValue<E>: Copy {
1118 type GlibType;
1119 const ZERO: E;
1120}
1121
1122#[repr(C)]
1133pub struct EnumerationValuesStorage<E: EnumerationValue<E>, const S: usize>([E; S]);
1134
1135impl<E: EnumerationValue<E>, const S: usize> EnumerationValuesStorage<E, S> {
1136 pub const fn new<const N: usize>(values: [E; N]) -> Self {
1139 #[repr(C)]
1140 #[derive(Copy, Clone)]
1141 struct Both<E: Copy, const N: usize>([E; N], [E; 1]);
1142
1143 #[repr(C)]
1144 union Transmute<E: Copy, const N: usize, const S: usize> {
1145 from: Both<E, N>,
1146 to: [E; S],
1147 }
1148
1149 unsafe {
1151 let all = Transmute {
1153 from: Both(values, [E::ZERO; 1]),
1154 }
1155 .to;
1156 Self(all)
1157 }
1158 }
1159}
1160
1161impl<E: EnumerationValue<E>, const S: usize> AsRef<EnumerationValues<E>>
1162 for EnumerationValuesStorage<E, S>
1163{
1164 fn as_ref(&self) -> &EnumerationValues<E> {
1165 unsafe { &*(&self.0 as *const [E] as *const EnumerationValues<E>) }
1167 }
1168}
1169
1170#[repr(C)]
1181pub struct EnumerationValues<E: EnumerationValue<E>>([E]);
1182
1183impl<E: EnumerationValue<E>> Deref for EnumerationValues<E> {
1184 type Target = [E];
1185
1186 fn deref(&self) -> &Self::Target {
1189 unsafe { std::slice::from_raw_parts(self.0.as_ptr(), self.0.len() - 1) }
1191 }
1192}
1193
1194#[doc(hidden)]
1195impl<'a, E: 'a + EnumerationValue<E>> ToGlibPtr<'a, *const E::GlibType> for EnumerationValues<E> {
1196 type Storage = &'a Self;
1197
1198 fn to_glib_none(&'a self) -> Stash<'a, *const E::GlibType, Self> {
1199 Stash(self.0.as_ptr() as *const E::GlibType, self)
1200 }
1201}
1202
1203#[cfg(test)]
1204mod tests {
1205 use super::*;
1206
1207 #[test]
1208 fn test_flags() {
1209 let flags = FlagsClass::new::<crate::BindingFlags>();
1210 let values = flags.values();
1211 let def1 = values
1212 .iter()
1213 .find(|v| v.name() == "G_BINDING_DEFAULT")
1214 .unwrap();
1215 let def2 = flags.value_by_name("G_BINDING_DEFAULT").unwrap();
1216 assert!(ptr::eq(def1, def2));
1217
1218 let value = flags.to_value(0).unwrap();
1219 let values = value.get::<Vec<&FlagsValue>>().unwrap();
1220 assert_eq!(values.len(), 0);
1221
1222 assert_eq!(def1.value(), crate::BindingFlags::DEFAULT.bits());
1223 }
1224}