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)]
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(&self) -> &str {
304 unsafe { CStr::from_ptr(self.0.value_name).to_str().unwrap() }
305 }
306
307 #[doc(alias = "get_nick")]
310 pub fn nick(&self) -> &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 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 let (_, v) = EnumValue::from_value(value).unwrap();
367 std::mem::transmute(v)
369 }
370}
371
372impl EnumerationValue<EnumValue> for EnumValue {
375 type GlibType = gobject_ffi::GEnumValue;
376 const ZERO: EnumValue = unsafe {
377 EnumValue::unsafe_from(gobject_ffi::GEnumValue {
378 value: 0,
379 value_name: ptr::null(),
380 value_nick: ptr::null(),
381 })
382 };
383}
384
385pub type EnumValuesStorage<const N: usize> = EnumerationValuesStorage<EnumValue, N>;
388
389pub type EnumValues = EnumerationValues<EnumValue>;
392
393pub struct EnumTypeChecker();
394unsafe impl crate::value::ValueTypeChecker for EnumTypeChecker {
395 type Error = InvalidEnumError;
396
397 fn check(value: &Value) -> Result<(), Self::Error> {
398 let t = value.type_();
399 if t.is_a(Type::ENUM) {
400 Ok(())
401 } else {
402 Err(InvalidEnumError)
403 }
404 }
405}
406
407#[derive(Clone, PartialEq, Eq, Debug)]
411pub struct InvalidEnumError;
412
413impl fmt::Display for InvalidEnumError {
414 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
415 write!(f, "Value is not an enum")
416 }
417}
418
419impl std::error::Error for InvalidEnumError {}
420
421#[doc(alias = "GFlagsClass")]
425#[repr(transparent)]
426pub struct FlagsClass(ptr::NonNull<gobject_ffi::GFlagsClass>);
427
428unsafe impl Send for FlagsClass {}
429unsafe impl Sync for FlagsClass {}
430
431impl fmt::Debug for FlagsClass {
432 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
433 f.debug_struct("FlagsClass")
434 .field("type", &self.type_())
435 .field("values", &self.values())
436 .finish()
437 }
438}
439
440impl FlagsClass {
441 pub fn new<T: StaticType + HasParamSpec<ParamSpec = ParamSpecFlags>>() -> Self {
446 Self::with_type(T::static_type()).expect("invalid flags class")
447 }
448 pub fn with_type(type_: Type) -> Option<Self> {
453 unsafe {
454 let is_flags: bool = from_glib(gobject_ffi::g_type_is_a(
455 type_.into_glib(),
456 gobject_ffi::G_TYPE_FLAGS,
457 ));
458 if !is_flags {
459 return None;
460 }
461
462 Some(FlagsClass(
463 ptr::NonNull::new(gobject_ffi::g_type_class_ref(type_.into_glib()) as *mut _)
464 .unwrap(),
465 ))
466 }
467 }
468
469 pub fn type_(&self) -> Type {
472 unsafe { from_glib(self.0.as_ref().g_type_class.g_type) }
473 }
474
475 #[doc(alias = "g_flags_get_first_value")]
481 #[doc(alias = "get_value")]
482 pub fn value(&self, value: u32) -> Option<&FlagsValue> {
483 unsafe {
484 let v = gobject_ffi::g_flags_get_first_value(self.0.as_ptr(), value);
485 if v.is_null() {
486 None
487 } else {
488 Some(&*(v as *const FlagsValue))
489 }
490 }
491 }
492
493 #[doc(alias = "g_flags_get_value_by_name")]
499 #[doc(alias = "get_value_by_name")]
500 pub fn value_by_name(&self, name: &str) -> Option<&FlagsValue> {
501 unsafe {
502 let v = gobject_ffi::g_flags_get_value_by_name(self.0.as_ptr(), name.to_glib_none().0);
503 if v.is_null() {
504 None
505 } else {
506 Some(&*(v as *const FlagsValue))
507 }
508 }
509 }
510
511 #[doc(alias = "g_flags_get_value_by_nick")]
517 #[doc(alias = "get_value_by_nick")]
518 pub fn value_by_nick(&self, nick: &str) -> Option<&FlagsValue> {
519 unsafe {
520 let v = gobject_ffi::g_flags_get_value_by_nick(self.0.as_ptr(), nick.to_glib_none().0);
521 if v.is_null() {
522 None
523 } else {
524 Some(&*(v as *const FlagsValue))
525 }
526 }
527 }
528
529 #[doc(alias = "get_values")]
532 pub fn values(&self) -> &[FlagsValue] {
533 unsafe {
534 if self.0.as_ref().n_values == 0 {
535 return &[];
536 }
537 std::slice::from_raw_parts(
538 self.0.as_ref().values as *const FlagsValue,
539 self.0.as_ref().n_values as usize,
540 )
541 }
542 }
543
544 pub fn to_value(&self, value: u32) -> Option<Value> {
547 self.value(value).map(|v| v.to_value(self))
548 }
549
550 pub fn to_value_by_name(&self, name: &str) -> Option<Value> {
553 self.value_by_name(name).map(|v| v.to_value(self))
554 }
555
556 pub fn to_value_by_nick(&self, nick: &str) -> Option<Value> {
559 self.value_by_nick(nick).map(|v| v.to_value(self))
560 }
561
562 pub fn is_set(&self, value: &Value, f: u32) -> bool {
565 unsafe {
566 if self.type_() != value.type_() {
567 return false;
568 }
569
570 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
571 flags & f != 0
572 }
573 }
574
575 pub fn is_set_by_name(&self, value: &Value, name: &str) -> bool {
578 unsafe {
579 if self.type_() != value.type_() {
580 return false;
581 }
582
583 if let Some(f) = self.value_by_name(name) {
584 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
585 flags & f.value() != 0
586 } else {
587 false
588 }
589 }
590 }
591
592 pub fn is_set_by_nick(&self, value: &Value, nick: &str) -> bool {
595 unsafe {
596 if self.type_() != value.type_() {
597 return false;
598 }
599
600 if let Some(f) = self.value_by_nick(nick) {
601 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
602 flags & f.value() != 0
603 } else {
604 false
605 }
606 }
607 }
608
609 #[doc(alias = "g_value_set_flags")]
616 pub fn set(&self, mut value: Value, f: u32) -> Result<Value, Value> {
617 unsafe {
618 if self.type_() != value.type_() {
619 return Err(value);
620 }
621
622 if let Some(f) = self.value(f) {
623 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
624 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value());
625 Ok(value)
626 } else {
627 Err(value)
628 }
629 }
630 }
631
632 pub fn set_by_name(&self, mut value: Value, name: &str) -> Result<Value, Value> {
639 unsafe {
640 if self.type_() != value.type_() {
641 return Err(value);
642 }
643
644 if let Some(f) = self.value_by_name(name) {
645 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
646 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value());
647 Ok(value)
648 } else {
649 Err(value)
650 }
651 }
652 }
653
654 pub fn set_by_nick(&self, mut value: Value, nick: &str) -> Result<Value, Value> {
661 unsafe {
662 if self.type_() != value.type_() {
663 return Err(value);
664 }
665
666 if let Some(f) = self.value_by_nick(nick) {
667 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
668 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value());
669 Ok(value)
670 } else {
671 Err(value)
672 }
673 }
674 }
675
676 pub fn unset(&self, mut value: Value, f: u32) -> Result<Value, Value> {
683 unsafe {
684 if self.type_() != value.type_() {
685 return Err(value);
686 }
687
688 if let Some(f) = self.value(f) {
689 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
690 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value());
691 Ok(value)
692 } else {
693 Err(value)
694 }
695 }
696 }
697
698 pub fn unset_by_name(&self, mut value: Value, name: &str) -> Result<Value, Value> {
705 unsafe {
706 if self.type_() != value.type_() {
707 return Err(value);
708 }
709
710 if let Some(f) = self.value_by_name(name) {
711 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
712 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value());
713 Ok(value)
714 } else {
715 Err(value)
716 }
717 }
718 }
719
720 pub fn unset_by_nick(&self, mut value: Value, nick: &str) -> Result<Value, Value> {
727 unsafe {
728 if self.type_() != value.type_() {
729 return Err(value);
730 }
731
732 if let Some(f) = self.value_by_nick(nick) {
733 let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
734 gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value());
735 Ok(value)
736 } else {
737 Err(value)
738 }
739 }
740 }
741
742 pub fn to_nick_string(&self, mut value: u32) -> String {
745 let mut s = String::new();
746 for val in self.values() {
747 let v = val.value();
748 if v != 0 && (value & v) == v {
749 value &= !v;
750 if !s.is_empty() {
751 s.push('|');
752 }
753 s.push_str(val.nick());
754 }
755 }
756 s
757 }
758
759 pub fn from_nick_string(&self, s: &str) -> Result<u32, ParseFlagsError> {
762 s.split('|').try_fold(0u32, |acc, flag| {
763 self.value_by_nick(flag.trim())
764 .map(|v| acc + v.value())
765 .ok_or_else(|| ParseFlagsError(flag.to_owned()))
766 })
767 }
768
769 pub fn builder(&self) -> FlagsBuilder {
773 FlagsBuilder::new(self)
774 }
775
776 pub fn builder_with_value(&self, value: Value) -> Option<FlagsBuilder> {
780 if self.type_() != value.type_() {
781 return None;
782 }
783
784 Some(FlagsBuilder::with_value(self, value))
785 }
786
787 #[doc(alias = "g_flags_complete_type_info")]
797 pub fn complete_type_info(
798 type_: Type,
799 const_static_values: &'static FlagsValues,
800 ) -> Option<TypeInfo> {
801 unsafe {
802 let is_flags: bool = from_glib(gobject_ffi::g_type_is_a(
803 type_.into_glib(),
804 gobject_ffi::G_TYPE_FLAGS,
805 ));
806 if !is_flags {
807 return None;
808 }
809
810 let info = TypeInfo::default();
811 gobject_ffi::g_flags_complete_type_info(
812 type_.into_glib(),
813 info.as_ptr(),
814 const_static_values.to_glib_none().0,
815 );
816 Some(info)
817 }
818 }
819}
820
821impl Drop for FlagsClass {
822 #[inline]
823 fn drop(&mut self) {
824 unsafe {
825 gobject_ffi::g_type_class_unref(self.0.as_ptr() as *mut _);
826 }
827 }
828}
829
830impl Clone for FlagsClass {
831 #[inline]
832 fn clone(&self) -> Self {
833 unsafe {
834 Self(ptr::NonNull::new(gobject_ffi::g_type_class_ref(self.type_().into_glib()) as *mut _).unwrap())
835 }
836 }
837}
838
839#[derive(Debug)]
840pub struct ParseFlagsError(String);
841
842impl std::error::Error for ParseFlagsError {}
843
844impl fmt::Display for ParseFlagsError {
845 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
846 write!(f, "Unknown flag: '{}'", self.0)
847 }
848}
849
850impl ParseFlagsError {
851 pub fn flag(&self) -> &str {
852 &self.0
853 }
854}
855
856#[doc(alias = "GFlagsValue")]
865#[derive(Copy, Clone)]
866#[repr(transparent)]
867pub struct FlagsValue(gobject_ffi::GFlagsValue);
868
869unsafe impl Send for FlagsValue {}
870unsafe impl Sync for FlagsValue {}
871
872impl fmt::Debug for FlagsValue {
873 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
874 f.debug_struct("FlagsValue")
875 .field("value", &self.value())
876 .field("name", &self.name())
877 .field("nick", &self.nick())
878 .finish()
879 }
880}
881
882impl FlagsValue {
883 pub const unsafe fn unsafe_from(g_value: gobject_ffi::GFlagsValue) -> Self {
889 Self(g_value)
890 }
891
892 #[doc(alias = "get_value")]
895 pub fn value(&self) -> u32 {
896 self.0.value
897 }
898
899 #[doc(alias = "get_name")]
902 pub fn name(&self) -> &str {
903 unsafe { CStr::from_ptr(self.0.value_name).to_str().unwrap() }
904 }
905
906 #[doc(alias = "get_nick")]
909 pub fn nick(&self) -> &str {
910 unsafe { CStr::from_ptr(self.0.value_nick).to_str().unwrap() }
911 }
912
913 pub fn to_value(&self, flags: &FlagsClass) -> Value {
916 unsafe {
917 let mut v = Value::from_type_unchecked(flags.type_());
918 gobject_ffi::g_value_set_flags(v.to_glib_none_mut().0, self.0.value);
919 v
920 }
921 }
922
923 pub fn from_value(value: &Value) -> Option<(FlagsClass, Vec<&FlagsValue>)> {
926 unsafe {
927 let flags_class = FlagsClass::with_type(value.type_())?;
928 let mut res = Vec::new();
929 let f = gobject_ffi::g_value_get_flags(value.to_glib_none().0);
930 for v in flags_class.values() {
931 if v.value() & f != 0 {
932 res.push(&*(v as *const FlagsValue));
933 }
934 }
935 Some((flags_class, res))
936 }
937 }
938}
939
940impl PartialEq for FlagsValue {
941 fn eq(&self, other: &Self) -> bool {
942 self.value().eq(&other.value())
943 }
944}
945
946impl Eq for FlagsValue {}
947
948impl UnsafeFrom<gobject_ffi::GFlagsValue> for FlagsValue {
949 unsafe fn unsafe_from(g_value: gobject_ffi::GFlagsValue) -> Self {
950 Self::unsafe_from(g_value)
951 }
952}
953
954impl EnumerationValue<FlagsValue> for FlagsValue {
957 type GlibType = gobject_ffi::GFlagsValue;
958 const ZERO: FlagsValue = unsafe {
959 FlagsValue::unsafe_from(gobject_ffi::GFlagsValue {
960 value: 0,
961 value_name: ptr::null(),
962 value_nick: ptr::null(),
963 })
964 };
965}
966
967pub type FlagsValuesStorage<const N: usize> = EnumerationValuesStorage<FlagsValue, N>;
970
971pub type FlagsValues = EnumerationValues<FlagsValue>;
974
975#[must_use = "The builder must be built to be used"]
994pub struct FlagsBuilder<'a>(&'a FlagsClass, Option<Value>);
995impl FlagsBuilder<'_> {
996 fn new(flags_class: &FlagsClass) -> FlagsBuilder {
997 let value = unsafe { Value::from_type_unchecked(flags_class.type_()) };
998 FlagsBuilder(flags_class, Some(value))
999 }
1000
1001 fn with_value(flags_class: &FlagsClass, value: Value) -> FlagsBuilder {
1002 FlagsBuilder(flags_class, Some(value))
1003 }
1004
1005 pub fn set(mut self, f: u32) -> Self {
1008 if let Some(value) = self.1.take() {
1009 self.1 = self.0.set(value, f).ok();
1010 }
1011
1012 self
1013 }
1014
1015 pub fn set_by_name(mut self, name: &str) -> Self {
1018 if let Some(value) = self.1.take() {
1019 self.1 = self.0.set_by_name(value, name).ok();
1020 }
1021
1022 self
1023 }
1024
1025 pub fn set_by_nick(mut self, nick: &str) -> Self {
1028 if let Some(value) = self.1.take() {
1029 self.1 = self.0.set_by_nick(value, nick).ok();
1030 }
1031
1032 self
1033 }
1034
1035 pub fn unset(mut self, f: u32) -> Self {
1038 if let Some(value) = self.1.take() {
1039 self.1 = self.0.unset(value, f).ok();
1040 }
1041
1042 self
1043 }
1044
1045 pub fn unset_by_name(mut self, name: &str) -> Self {
1048 if let Some(value) = self.1.take() {
1049 self.1 = self.0.unset_by_name(value, name).ok();
1050 }
1051
1052 self
1053 }
1054
1055 pub fn unset_by_nick(mut self, nick: &str) -> Self {
1058 if let Some(value) = self.1.take() {
1059 self.1 = self.0.unset_by_nick(value, nick).ok();
1060 }
1061
1062 self
1063 }
1064
1065 #[must_use = "Value returned from the builder should probably be used"]
1068 pub fn build(self) -> Option<Value> {
1069 self.1
1070 }
1071}
1072
1073unsafe impl<'a> crate::value::FromValue<'a> for Vec<&FlagsValue> {
1074 type Checker = FlagsTypeChecker;
1075
1076 unsafe fn from_value(value: &'a Value) -> Self {
1077 let (_, v) = FlagsValue::from_value(value).unwrap();
1078 std::mem::transmute(v)
1080 }
1081}
1082
1083pub struct FlagsTypeChecker();
1084unsafe impl crate::value::ValueTypeChecker for FlagsTypeChecker {
1085 type Error = InvalidFlagsError;
1086
1087 fn check(value: &Value) -> Result<(), Self::Error> {
1088 let t = value.type_();
1089 if t.is_a(Type::FLAGS) {
1090 Ok(())
1091 } else {
1092 Err(InvalidFlagsError)
1093 }
1094 }
1095}
1096
1097#[derive(Clone, PartialEq, Eq, Debug)]
1101pub struct InvalidFlagsError;
1102
1103impl fmt::Display for InvalidFlagsError {
1104 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1105 write!(f, "Value is not a flags")
1106 }
1107}
1108
1109impl std::error::Error for InvalidFlagsError {}
1110
1111pub trait EnumerationValue<E>: Copy {
1114 type GlibType;
1115 const ZERO: E;
1116}
1117
1118#[repr(C)]
1129pub struct EnumerationValuesStorage<E: EnumerationValue<E>, const S: usize>([E; S]);
1130
1131impl<E: EnumerationValue<E>, const S: usize> EnumerationValuesStorage<E, S> {
1132 pub const fn new<const N: usize>(values: [E; N]) -> Self {
1135 #[repr(C)]
1136 #[derive(Copy, Clone)]
1137 struct Both<E: Copy, const N: usize>([E; N], [E; 1]);
1138
1139 #[repr(C)]
1140 union Transmute<E: Copy, const N: usize, const S: usize> {
1141 from: Both<E, N>,
1142 to: [E; S],
1143 }
1144
1145 unsafe {
1147 let all = Transmute {
1149 from: Both(values, [E::ZERO; 1]),
1150 }
1151 .to;
1152 Self(all)
1153 }
1154 }
1155}
1156
1157impl<E: EnumerationValue<E>, const S: usize> AsRef<EnumerationValues<E>>
1158 for EnumerationValuesStorage<E, S>
1159{
1160 fn as_ref(&self) -> &EnumerationValues<E> {
1161 unsafe { &*(&self.0 as *const [E] as *const EnumerationValues<E>) }
1163 }
1164}
1165
1166#[repr(C)]
1177pub struct EnumerationValues<E: EnumerationValue<E>>([E]);
1178
1179impl<E: EnumerationValue<E>> Deref for EnumerationValues<E> {
1180 type Target = [E];
1181
1182 fn deref(&self) -> &Self::Target {
1185 unsafe { std::slice::from_raw_parts(self.0.as_ptr(), self.0.len() - 1) }
1187 }
1188}
1189
1190#[doc(hidden)]
1191impl<'a, E: 'a + EnumerationValue<E>> ToGlibPtr<'a, *const E::GlibType> for EnumerationValues<E> {
1192 type Storage = &'a Self;
1193
1194 fn to_glib_none(&'a self) -> Stash<'a, *const E::GlibType, Self> {
1195 Stash(self.0.as_ptr() as *const E::GlibType, self)
1196 }
1197}
1198
1199#[cfg(test)]
1200mod tests {
1201 use super::*;
1202
1203 #[test]
1204 fn test_flags() {
1205 let flags = FlagsClass::new::<crate::BindingFlags>();
1206 let values = flags.values();
1207 let def1 = values
1208 .iter()
1209 .find(|v| v.name() == "G_BINDING_DEFAULT")
1210 .unwrap();
1211 let def2 = flags.value_by_name("G_BINDING_DEFAULT").unwrap();
1212 assert!(ptr::eq(def1, def2));
1213
1214 let value = flags.to_value(0).unwrap();
1215 let values = value.get::<Vec<&FlagsValue>>().unwrap();
1216 assert_eq!(values.len(), 0);
1217
1218 assert_eq!(def1.value(), crate::BindingFlags::DEFAULT.bits());
1219 }
1220}