1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use std::{cmp, ffi::CStr, fmt, ptr}; |
4 | |
5 | use crate::{ |
6 | translate::*, |
7 | value::{FromValue, ValueTypeChecker}, |
8 | HasParamSpec, ParamSpecEnum, ParamSpecFlags, StaticType, Type, Value, |
9 | }; |
10 | |
11 | #[derive (Clone, Copy, Debug, Eq, PartialEq, Hash)] |
12 | pub enum UserDirectory { |
13 | #[doc (alias = "G_USER_DIRECTORY_DESKTOP" )] |
14 | Desktop, |
15 | #[doc (alias = "G_USER_DIRECTORY_DOCUMENTS" )] |
16 | Documents, |
17 | #[doc (alias = "G_USER_DIRECTORY_DOWNLOAD" )] |
18 | Downloads, |
19 | #[doc (alias = "G_USER_DIRECTORY_MUSIC" )] |
20 | Music, |
21 | #[doc (alias = "G_USER_DIRECTORY_PICTURES" )] |
22 | Pictures, |
23 | #[doc (alias = "G_USER_DIRECTORY_PUBLIC_SHARE" )] |
24 | PublicShare, |
25 | #[doc (alias = "G_USER_DIRECTORY_TEMPLATES" )] |
26 | Templates, |
27 | #[doc (alias = "G_USER_DIRECTORY_VIDEOS" )] |
28 | Videos, |
29 | } |
30 | |
31 | #[doc (hidden)] |
32 | impl IntoGlib for UserDirectory { |
33 | type GlibType = ffi::GUserDirectory; |
34 | |
35 | #[inline ] |
36 | fn into_glib(self) -> ffi::GUserDirectory { |
37 | match self { |
38 | Self::Desktop => ffi::G_USER_DIRECTORY_DESKTOP, |
39 | Self::Documents => ffi::G_USER_DIRECTORY_DOCUMENTS, |
40 | Self::Downloads => ffi::G_USER_DIRECTORY_DOWNLOAD, |
41 | Self::Music => ffi::G_USER_DIRECTORY_MUSIC, |
42 | Self::Pictures => ffi::G_USER_DIRECTORY_PICTURES, |
43 | Self::PublicShare => ffi::G_USER_DIRECTORY_PUBLIC_SHARE, |
44 | Self::Templates => ffi::G_USER_DIRECTORY_TEMPLATES, |
45 | Self::Videos => ffi::G_USER_DIRECTORY_VIDEOS, |
46 | } |
47 | } |
48 | } |
49 | |
50 | // rustdoc-stripper-ignore-next |
51 | /// Representation of an `enum` for dynamically, at runtime, querying the values of the enum and |
52 | /// using them. |
53 | #[doc (alias = "GEnumClass" )] |
54 | #[repr (transparent)] |
55 | pub struct EnumClass(ptr::NonNull<gobject_ffi::GEnumClass>); |
56 | |
57 | unsafe impl Send for EnumClass {} |
58 | unsafe impl Sync for EnumClass {} |
59 | |
60 | impl fmt::Debug for EnumClass { |
61 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
62 | f&mut DebugStruct<'_, '_>.debug_struct("EnumClass" ) |
63 | .field("type" , &self.type_()) |
64 | .field(name:"values" , &self.values()) |
65 | .finish() |
66 | } |
67 | } |
68 | |
69 | impl EnumClass { |
70 | // rustdoc-stripper-ignore-next |
71 | /// Create a new `EnumClass` from a static type `T`. |
72 | /// |
73 | /// Panics if `T` is not representing an enum. |
74 | pub fn new<T: StaticType + HasParamSpec<ParamSpec = ParamSpecEnum>>() -> Self { |
75 | Self::with_type(T::static_type()).expect("invalid enum class" ) |
76 | } |
77 | // rustdoc-stripper-ignore-next |
78 | /// Create a new `EnumClass` from a `Type`. |
79 | /// |
80 | /// Returns `None` if `type_` is not representing an enum. |
81 | pub fn with_type(type_: Type) -> Option<Self> { |
82 | unsafe { |
83 | let is_enum: bool = from_glib(gobject_ffi::g_type_is_a( |
84 | type_.into_glib(), |
85 | gobject_ffi::G_TYPE_ENUM, |
86 | )); |
87 | if !is_enum { |
88 | return None; |
89 | } |
90 | |
91 | Some(EnumClass( |
92 | ptr::NonNull::new(gobject_ffi::g_type_class_ref(type_.into_glib()) as *mut _) |
93 | .unwrap(), |
94 | )) |
95 | } |
96 | } |
97 | |
98 | // rustdoc-stripper-ignore-next |
99 | /// `Type` of the enum. |
100 | pub fn type_(&self) -> Type { |
101 | unsafe { from_glib(self.0.as_ref().g_type_class.g_type) } |
102 | } |
103 | |
104 | // rustdoc-stripper-ignore-next |
105 | /// Gets `EnumValue` by integer `value`, if existing. |
106 | /// |
107 | /// Returns `None` if the enum does not contain any value |
108 | /// with `value`. |
109 | #[doc (alias = "g_enum_get_value" )] |
110 | #[doc (alias = "get_value" )] |
111 | pub fn value(&self, value: i32) -> Option<&EnumValue> { |
112 | unsafe { |
113 | let v = gobject_ffi::g_enum_get_value(self.0.as_ptr(), value); |
114 | if v.is_null() { |
115 | None |
116 | } else { |
117 | Some(&*(v as *const EnumValue)) |
118 | } |
119 | } |
120 | } |
121 | |
122 | // rustdoc-stripper-ignore-next |
123 | /// Gets `EnumValue` by string name `name`, if existing. |
124 | /// |
125 | /// Returns `None` if the enum does not contain any value |
126 | /// with name `name`. |
127 | #[doc (alias = "g_enum_get_value_by_name" )] |
128 | #[doc (alias = "get_value_by_name" )] |
129 | pub fn value_by_name(&self, name: &str) -> Option<&EnumValue> { |
130 | unsafe { |
131 | let v = gobject_ffi::g_enum_get_value_by_name(self.0.as_ptr(), name.to_glib_none().0); |
132 | if v.is_null() { |
133 | None |
134 | } else { |
135 | Some(&*(v as *const EnumValue)) |
136 | } |
137 | } |
138 | } |
139 | |
140 | // rustdoc-stripper-ignore-next |
141 | /// Gets `EnumValue` by string nick `nick`, if existing. |
142 | /// |
143 | /// Returns `None` if the enum does not contain any value |
144 | /// with nick `nick`. |
145 | #[doc (alias = "g_enum_get_value_by_nick" )] |
146 | #[doc (alias = "get_value_by_nick" )] |
147 | pub fn value_by_nick(&self, nick: &str) -> Option<&EnumValue> { |
148 | unsafe { |
149 | let v = gobject_ffi::g_enum_get_value_by_nick(self.0.as_ptr(), nick.to_glib_none().0); |
150 | if v.is_null() { |
151 | None |
152 | } else { |
153 | Some(&*(v as *const EnumValue)) |
154 | } |
155 | } |
156 | } |
157 | |
158 | // rustdoc-stripper-ignore-next |
159 | /// Gets all `EnumValue` of this `EnumClass`. |
160 | #[doc (alias = "get_values" )] |
161 | pub fn values(&self) -> &[EnumValue] { |
162 | unsafe { |
163 | if self.0.as_ref().n_values == 0 { |
164 | return &[]; |
165 | } |
166 | std::slice::from_raw_parts( |
167 | self.0.as_ref().values as *const EnumValue, |
168 | self.0.as_ref().n_values as usize, |
169 | ) |
170 | } |
171 | } |
172 | |
173 | // rustdoc-stripper-ignore-next |
174 | /// Converts integer `value` to a `Value`, if part of the enum. |
175 | pub fn to_value(&self, value: i32) -> Option<Value> { |
176 | self.value(value).map(|v| v.to_value(self)) |
177 | } |
178 | |
179 | // rustdoc-stripper-ignore-next |
180 | /// Converts string name `name` to a `Value`, if part of the enum. |
181 | pub fn to_value_by_name(&self, name: &str) -> Option<Value> { |
182 | self.value_by_name(name).map(|v| v.to_value(self)) |
183 | } |
184 | |
185 | // rustdoc-stripper-ignore-next |
186 | /// Converts string nick `nick` to a `Value`, if part of the enum. |
187 | pub fn to_value_by_nick(&self, nick: &str) -> Option<Value> { |
188 | self.value_by_nick(nick).map(|v| v.to_value(self)) |
189 | } |
190 | } |
191 | |
192 | impl Drop for EnumClass { |
193 | #[inline ] |
194 | fn drop(&mut self) { |
195 | unsafe { |
196 | gobject_ffi::g_type_class_unref(self.0.as_ptr() as *mut _); |
197 | } |
198 | } |
199 | } |
200 | |
201 | impl Clone for EnumClass { |
202 | #[inline ] |
203 | fn clone(&self) -> Self { |
204 | unsafe { |
205 | Self(ptr::NonNull::new(ptr:gobject_ffi::g_type_class_ref(self.type_().into_glib()) as *mut _).unwrap()) |
206 | } |
207 | } |
208 | } |
209 | |
210 | // rustdoc-stripper-ignore-next |
211 | /// Representation of a single enum value of an `EnumClass`. |
212 | #[doc (alias = "GEnumValue" )] |
213 | #[repr (transparent)] |
214 | pub struct EnumValue(gobject_ffi::GEnumValue); |
215 | |
216 | unsafe impl Send for EnumValue {} |
217 | unsafe impl Sync for EnumValue {} |
218 | |
219 | impl fmt::Debug for EnumValue { |
220 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
221 | f&mut DebugStruct<'_, '_>.debug_struct("EnumValue" ) |
222 | .field("value" , &self.value()) |
223 | .field("name" , &self.name()) |
224 | .field(name:"nick" , &self.nick()) |
225 | .finish() |
226 | } |
227 | } |
228 | |
229 | impl EnumValue { |
230 | // rustdoc-stripper-ignore-next |
231 | /// Get integer value corresponding to the value. |
232 | #[doc (alias = "get_value" )] |
233 | pub fn value(&self) -> i32 { |
234 | self.0.value |
235 | } |
236 | |
237 | // rustdoc-stripper-ignore-next |
238 | /// Get name corresponding to the value. |
239 | #[doc (alias = "get_name" )] |
240 | pub fn name(&self) -> &str { |
241 | unsafe { CStr::from_ptr(self.0.value_name).to_str().unwrap() } |
242 | } |
243 | |
244 | // rustdoc-stripper-ignore-next |
245 | /// Get nick corresponding to the value. |
246 | #[doc (alias = "get_nick" )] |
247 | pub fn nick(&self) -> &str { |
248 | unsafe { CStr::from_ptr(self.0.value_nick).to_str().unwrap() } |
249 | } |
250 | |
251 | // rustdoc-stripper-ignore-next |
252 | /// Convert enum value to a `Value`. |
253 | pub fn to_value(&self, enum_: &EnumClass) -> Value { |
254 | unsafe { |
255 | let mut v = Value::from_type_unchecked(enum_.type_()); |
256 | gobject_ffi::g_value_set_enum(v.to_glib_none_mut().0, self.0.value); |
257 | v |
258 | } |
259 | } |
260 | |
261 | // rustdoc-stripper-ignore-next |
262 | /// Convert enum value from a `Value`. |
263 | pub fn from_value(value: &Value) -> Option<(EnumClass, &EnumValue)> { |
264 | unsafe { |
265 | let enum_class = EnumClass::with_type(value.type_())?; |
266 | let v = enum_class.value(gobject_ffi::g_value_get_enum(value.to_glib_none().0))?; |
267 | let v = &*(v as *const EnumValue); |
268 | Some((enum_class, v)) |
269 | } |
270 | } |
271 | } |
272 | |
273 | impl PartialEq for EnumValue { |
274 | fn eq(&self, other: &Self) -> bool { |
275 | self.value().eq(&other.value()) |
276 | } |
277 | } |
278 | |
279 | impl Eq for EnumValue {} |
280 | |
281 | impl PartialOrd for EnumValue { |
282 | fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { |
283 | Some(self.cmp(other)) |
284 | } |
285 | } |
286 | |
287 | impl Ord for EnumValue { |
288 | fn cmp(&self, other: &Self) -> cmp::Ordering { |
289 | self.value().cmp(&other.value()) |
290 | } |
291 | } |
292 | |
293 | unsafe impl<'a, 'b> FromValue<'a> for &'b EnumValue { |
294 | type Checker = EnumTypeChecker; |
295 | |
296 | unsafe fn from_value(value: &'a Value) -> Self { |
297 | let (_, v: &EnumValue) = EnumValue::from_value(value).unwrap(); |
298 | // SAFETY: The enum class and its values live forever |
299 | std::mem::transmute(src:v) |
300 | } |
301 | } |
302 | |
303 | pub struct EnumTypeChecker(); |
304 | unsafe impl ValueTypeChecker for EnumTypeChecker { |
305 | type Error = InvalidEnumError; |
306 | |
307 | fn check(value: &Value) -> Result<(), Self::Error> { |
308 | let t: Type = value.type_(); |
309 | if t.is_a(Type::ENUM) { |
310 | Ok(()) |
311 | } else { |
312 | Err(InvalidEnumError) |
313 | } |
314 | } |
315 | } |
316 | |
317 | // rustdoc-stripper-ignore-next |
318 | /// An error returned from the [`get`](struct.Value.html#method.get) function |
319 | /// on a [`Value`](struct.Value.html) for enum types. |
320 | #[derive (Clone, PartialEq, Eq, Debug)] |
321 | pub struct InvalidEnumError; |
322 | |
323 | impl fmt::Display for InvalidEnumError { |
324 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
325 | write!(f, "Value is not an enum" ) |
326 | } |
327 | } |
328 | |
329 | impl std::error::Error for InvalidEnumError {} |
330 | |
331 | // rustdoc-stripper-ignore-next |
332 | /// Representation of a `flags` for dynamically, at runtime, querying the values of the enum and |
333 | /// using them |
334 | #[doc (alias = "GFlagsClass" )] |
335 | #[repr (transparent)] |
336 | pub struct FlagsClass(ptr::NonNull<gobject_ffi::GFlagsClass>); |
337 | |
338 | unsafe impl Send for FlagsClass {} |
339 | unsafe impl Sync for FlagsClass {} |
340 | |
341 | impl fmt::Debug for FlagsClass { |
342 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
343 | f&mut DebugStruct<'_, '_>.debug_struct("FlagsClass" ) |
344 | .field("type" , &self.type_()) |
345 | .field(name:"values" , &self.values()) |
346 | .finish() |
347 | } |
348 | } |
349 | |
350 | impl FlagsClass { |
351 | // rustdoc-stripper-ignore-next |
352 | /// Create a new `FlagsClass` from a static type `T`. |
353 | /// |
354 | /// Panics if `T` is not representing an flags type. |
355 | pub fn new<T: StaticType + HasParamSpec<ParamSpec = ParamSpecFlags>>() -> Self { |
356 | Self::with_type(T::static_type()).expect("invalid flags class" ) |
357 | } |
358 | // rustdoc-stripper-ignore-next |
359 | /// Create a new `FlagsClass` from a `Type` |
360 | /// |
361 | /// Returns `None` if `type_` is not representing a flags type. |
362 | pub fn with_type(type_: Type) -> Option<Self> { |
363 | unsafe { |
364 | let is_flags: bool = from_glib(gobject_ffi::g_type_is_a( |
365 | type_.into_glib(), |
366 | gobject_ffi::G_TYPE_FLAGS, |
367 | )); |
368 | if !is_flags { |
369 | return None; |
370 | } |
371 | |
372 | Some(FlagsClass( |
373 | ptr::NonNull::new(gobject_ffi::g_type_class_ref(type_.into_glib()) as *mut _) |
374 | .unwrap(), |
375 | )) |
376 | } |
377 | } |
378 | |
379 | // rustdoc-stripper-ignore-next |
380 | /// `Type` of the flags. |
381 | pub fn type_(&self) -> Type { |
382 | unsafe { from_glib(self.0.as_ref().g_type_class.g_type) } |
383 | } |
384 | |
385 | // rustdoc-stripper-ignore-next |
386 | /// Gets `FlagsValue` by integer `value`, if existing. |
387 | /// |
388 | /// Returns `None` if the flags do not contain any value |
389 | /// with `value`. |
390 | #[doc (alias = "g_flags_get_first_value" )] |
391 | #[doc (alias = "get_value" )] |
392 | pub fn value(&self, value: u32) -> Option<&FlagsValue> { |
393 | unsafe { |
394 | let v = gobject_ffi::g_flags_get_first_value(self.0.as_ptr(), value); |
395 | if v.is_null() { |
396 | None |
397 | } else { |
398 | Some(&*(v as *const FlagsValue)) |
399 | } |
400 | } |
401 | } |
402 | |
403 | // rustdoc-stripper-ignore-next |
404 | /// Gets `FlagsValue` by string name `name`, if existing. |
405 | /// |
406 | /// Returns `None` if the flags do not contain any value |
407 | /// with name `name`. |
408 | #[doc (alias = "g_flags_get_value_by_name" )] |
409 | #[doc (alias = "get_value_by_name" )] |
410 | pub fn value_by_name(&self, name: &str) -> Option<&FlagsValue> { |
411 | unsafe { |
412 | let v = gobject_ffi::g_flags_get_value_by_name(self.0.as_ptr(), name.to_glib_none().0); |
413 | if v.is_null() { |
414 | None |
415 | } else { |
416 | Some(&*(v as *const FlagsValue)) |
417 | } |
418 | } |
419 | } |
420 | |
421 | // rustdoc-stripper-ignore-next |
422 | /// Gets `FlagsValue` by string nick `nick`, if existing. |
423 | /// |
424 | /// Returns `None` if the flags do not contain any value |
425 | /// with nick `nick`. |
426 | #[doc (alias = "g_flags_get_value_by_nick" )] |
427 | #[doc (alias = "get_value_by_nick" )] |
428 | pub fn value_by_nick(&self, nick: &str) -> Option<&FlagsValue> { |
429 | unsafe { |
430 | let v = gobject_ffi::g_flags_get_value_by_nick(self.0.as_ptr(), nick.to_glib_none().0); |
431 | if v.is_null() { |
432 | None |
433 | } else { |
434 | Some(&*(v as *const FlagsValue)) |
435 | } |
436 | } |
437 | } |
438 | |
439 | // rustdoc-stripper-ignore-next |
440 | /// Gets all `FlagsValue` of this `FlagsClass`. |
441 | #[doc (alias = "get_values" )] |
442 | pub fn values(&self) -> &[FlagsValue] { |
443 | unsafe { |
444 | if self.0.as_ref().n_values == 0 { |
445 | return &[]; |
446 | } |
447 | std::slice::from_raw_parts( |
448 | self.0.as_ref().values as *const FlagsValue, |
449 | self.0.as_ref().n_values as usize, |
450 | ) |
451 | } |
452 | } |
453 | |
454 | // rustdoc-stripper-ignore-next |
455 | /// Converts integer `value` to a `Value`, if part of the flags. |
456 | pub fn to_value(&self, value: u32) -> Option<Value> { |
457 | self.value(value).map(|v| v.to_value(self)) |
458 | } |
459 | |
460 | // rustdoc-stripper-ignore-next |
461 | /// Converts string name `name` to a `Value`, if part of the flags. |
462 | pub fn to_value_by_name(&self, name: &str) -> Option<Value> { |
463 | self.value_by_name(name).map(|v| v.to_value(self)) |
464 | } |
465 | |
466 | // rustdoc-stripper-ignore-next |
467 | /// Converts string nick `nick` to a `Value`, if part of the flags. |
468 | pub fn to_value_by_nick(&self, nick: &str) -> Option<Value> { |
469 | self.value_by_nick(nick).map(|v| v.to_value(self)) |
470 | } |
471 | |
472 | // rustdoc-stripper-ignore-next |
473 | /// Checks if the flags corresponding to integer `f` is set in `value`. |
474 | pub fn is_set(&self, value: &Value, f: u32) -> bool { |
475 | unsafe { |
476 | if self.type_() != value.type_() { |
477 | return false; |
478 | } |
479 | |
480 | let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0); |
481 | flags & f != 0 |
482 | } |
483 | } |
484 | |
485 | // rustdoc-stripper-ignore-next |
486 | /// Checks if the flags corresponding to string name `name` is set in `value`. |
487 | pub fn is_set_by_name(&self, value: &Value, name: &str) -> bool { |
488 | unsafe { |
489 | if self.type_() != value.type_() { |
490 | return false; |
491 | } |
492 | |
493 | if let Some(f) = self.value_by_name(name) { |
494 | let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0); |
495 | flags & f.value() != 0 |
496 | } else { |
497 | false |
498 | } |
499 | } |
500 | } |
501 | |
502 | // rustdoc-stripper-ignore-next |
503 | /// Checks if the flags corresponding to string nick `nick` is set in `value`. |
504 | pub fn is_set_by_nick(&self, value: &Value, nick: &str) -> bool { |
505 | unsafe { |
506 | if self.type_() != value.type_() { |
507 | return false; |
508 | } |
509 | |
510 | if let Some(f) = self.value_by_nick(nick) { |
511 | let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0); |
512 | flags & f.value() != 0 |
513 | } else { |
514 | false |
515 | } |
516 | } |
517 | } |
518 | |
519 | // rustdoc-stripper-ignore-next |
520 | /// Set flags value corresponding to integer `f` in `value`, if part of that flags. If the |
521 | /// flag is already set, it will succeed without doing any changes. |
522 | /// |
523 | /// Returns `Ok(value)` with the flag set if successful, or `Err(value)` with the original |
524 | /// value otherwise. |
525 | #[doc (alias = "g_value_set_flags" )] |
526 | pub fn set(&self, mut value: Value, f: u32) -> Result<Value, Value> { |
527 | unsafe { |
528 | if self.type_() != value.type_() { |
529 | return Err(value); |
530 | } |
531 | |
532 | if let Some(f) = self.value(f) { |
533 | let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0); |
534 | gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value()); |
535 | Ok(value) |
536 | } else { |
537 | Err(value) |
538 | } |
539 | } |
540 | } |
541 | |
542 | // rustdoc-stripper-ignore-next |
543 | /// Set flags value corresponding to string name `name` in `value`, if part of that flags. |
544 | /// If the flag is already set, it will succeed without doing any changes. |
545 | /// |
546 | /// Returns `Ok(value)` with the flag set if successful, or `Err(value)` with the original |
547 | /// value otherwise. |
548 | pub fn set_by_name(&self, mut value: Value, name: &str) -> Result<Value, Value> { |
549 | unsafe { |
550 | if self.type_() != value.type_() { |
551 | return Err(value); |
552 | } |
553 | |
554 | if let Some(f) = self.value_by_name(name) { |
555 | let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0); |
556 | gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value()); |
557 | Ok(value) |
558 | } else { |
559 | Err(value) |
560 | } |
561 | } |
562 | } |
563 | |
564 | // rustdoc-stripper-ignore-next |
565 | /// Set flags value corresponding to string nick `nick` in `value`, if part of that flags. |
566 | /// If the flag is already set, it will succeed without doing any changes. |
567 | /// |
568 | /// Returns `Ok(value)` with the flag set if successful, or `Err(value)` with the original |
569 | /// value otherwise. |
570 | pub fn set_by_nick(&self, mut value: Value, nick: &str) -> Result<Value, Value> { |
571 | unsafe { |
572 | if self.type_() != value.type_() { |
573 | return Err(value); |
574 | } |
575 | |
576 | if let Some(f) = self.value_by_nick(nick) { |
577 | let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0); |
578 | gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags | f.value()); |
579 | Ok(value) |
580 | } else { |
581 | Err(value) |
582 | } |
583 | } |
584 | } |
585 | |
586 | // rustdoc-stripper-ignore-next |
587 | /// Unset flags value corresponding to integer `f` in `value`, if part of that flags. |
588 | /// If the flag is already unset, it will succeed without doing any changes. |
589 | /// |
590 | /// Returns `Ok(value)` with the flag unset if successful, or `Err(value)` with the original |
591 | /// value otherwise. |
592 | pub fn unset(&self, mut value: Value, f: u32) -> Result<Value, Value> { |
593 | unsafe { |
594 | if self.type_() != value.type_() { |
595 | return Err(value); |
596 | } |
597 | |
598 | if let Some(f) = self.value(f) { |
599 | let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0); |
600 | gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value()); |
601 | Ok(value) |
602 | } else { |
603 | Err(value) |
604 | } |
605 | } |
606 | } |
607 | |
608 | // rustdoc-stripper-ignore-next |
609 | /// Unset flags value corresponding to string name `name` in `value`, if part of that flags. |
610 | /// If the flag is already unset, it will succeed without doing any changes. |
611 | /// |
612 | /// Returns `Ok(value)` with the flag unset if successful, or `Err(value)` with the original |
613 | /// value otherwise. |
614 | pub fn unset_by_name(&self, mut value: Value, name: &str) -> Result<Value, Value> { |
615 | unsafe { |
616 | if self.type_() != value.type_() { |
617 | return Err(value); |
618 | } |
619 | |
620 | if let Some(f) = self.value_by_name(name) { |
621 | let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0); |
622 | gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value()); |
623 | Ok(value) |
624 | } else { |
625 | Err(value) |
626 | } |
627 | } |
628 | } |
629 | |
630 | // rustdoc-stripper-ignore-next |
631 | /// Unset flags value corresponding to string nick `nick` in `value`, if part of that flags. |
632 | /// If the flag is already unset, it will succeed without doing any changes. |
633 | /// |
634 | /// Returns `Ok(value)` with the flag unset if successful, or `Err(value)` with the original |
635 | /// value otherwise. |
636 | pub fn unset_by_nick(&self, mut value: Value, nick: &str) -> Result<Value, Value> { |
637 | unsafe { |
638 | if self.type_() != value.type_() { |
639 | return Err(value); |
640 | } |
641 | |
642 | if let Some(f) = self.value_by_nick(nick) { |
643 | let flags = gobject_ffi::g_value_get_flags(value.to_glib_none().0); |
644 | gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, flags & !f.value()); |
645 | Ok(value) |
646 | } else { |
647 | Err(value) |
648 | } |
649 | } |
650 | } |
651 | |
652 | // rustdoc-stripper-ignore-next |
653 | /// Converts an integer `value` to a string of nicks separated by `|`. |
654 | pub fn to_nick_string(&self, mut value: u32) -> String { |
655 | let mut s = String::new(); |
656 | for val in self.values() { |
657 | let v = val.value(); |
658 | if v != 0 && (value & v) == v { |
659 | value &= !v; |
660 | if !s.is_empty() { |
661 | s.push('|' ); |
662 | } |
663 | s.push_str(val.nick()); |
664 | } |
665 | } |
666 | s |
667 | } |
668 | |
669 | // rustdoc-stripper-ignore-next |
670 | /// Converts a string of nicks `s` separated by `|` to an integer value. |
671 | pub fn from_nick_string(&self, s: &str) -> Result<u32, ParseFlagsError> { |
672 | s.split('|' ).try_fold(0u32, |acc, flag| { |
673 | self.value_by_nick(flag.trim()) |
674 | .map(|v| acc + v.value()) |
675 | .ok_or_else(|| ParseFlagsError(flag.to_owned())) |
676 | }) |
677 | } |
678 | |
679 | // rustdoc-stripper-ignore-next |
680 | /// Returns a new `FlagsBuilder` for conveniently setting/unsetting flags |
681 | /// and building a `Value`. |
682 | pub fn builder(&self) -> FlagsBuilder { |
683 | FlagsBuilder::new(self) |
684 | } |
685 | |
686 | // rustdoc-stripper-ignore-next |
687 | /// Returns a new `FlagsBuilder` for conveniently setting/unsetting flags |
688 | /// and building a `Value`. The `Value` is initialized with `value`. |
689 | pub fn builder_with_value(&self, value: Value) -> Option<FlagsBuilder> { |
690 | if self.type_() != value.type_() { |
691 | return None; |
692 | } |
693 | |
694 | Some(FlagsBuilder::with_value(self, value)) |
695 | } |
696 | } |
697 | |
698 | impl Drop for FlagsClass { |
699 | #[inline ] |
700 | fn drop(&mut self) { |
701 | unsafe { |
702 | gobject_ffi::g_type_class_unref(self.0.as_ptr() as *mut _); |
703 | } |
704 | } |
705 | } |
706 | |
707 | impl Clone for FlagsClass { |
708 | #[inline ] |
709 | fn clone(&self) -> Self { |
710 | unsafe { |
711 | Self(ptr::NonNull::new(ptr:gobject_ffi::g_type_class_ref(self.type_().into_glib()) as *mut _).unwrap()) |
712 | } |
713 | } |
714 | } |
715 | |
716 | #[derive (Debug)] |
717 | pub struct ParseFlagsError(String); |
718 | |
719 | impl std::error::Error for ParseFlagsError {} |
720 | |
721 | impl fmt::Display for ParseFlagsError { |
722 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
723 | write!(f, "Unknown flag: ' {}'" , self.0) |
724 | } |
725 | } |
726 | |
727 | impl ParseFlagsError { |
728 | pub fn flag(&self) -> &str { |
729 | &self.0 |
730 | } |
731 | } |
732 | |
733 | // rustdoc-stripper-ignore-next |
734 | /// Representation of a single flags value of a `FlagsClass`. |
735 | #[doc (alias = "GFlagsValue" )] |
736 | #[repr (transparent)] |
737 | pub struct FlagsValue(gobject_ffi::GFlagsValue); |
738 | |
739 | unsafe impl Send for FlagsValue {} |
740 | unsafe impl Sync for FlagsValue {} |
741 | |
742 | impl fmt::Debug for FlagsValue { |
743 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
744 | f&mut DebugStruct<'_, '_>.debug_struct("FlagsValue" ) |
745 | .field("value" , &self.value()) |
746 | .field("name" , &self.name()) |
747 | .field(name:"nick" , &self.nick()) |
748 | .finish() |
749 | } |
750 | } |
751 | |
752 | impl FlagsValue { |
753 | // rustdoc-stripper-ignore-next |
754 | /// Get integer value corresponding to the value. |
755 | #[doc (alias = "get_value" )] |
756 | pub fn value(&self) -> u32 { |
757 | self.0.value |
758 | } |
759 | |
760 | // rustdoc-stripper-ignore-next |
761 | /// Get name corresponding to the value. |
762 | #[doc (alias = "get_name" )] |
763 | pub fn name(&self) -> &str { |
764 | unsafe { CStr::from_ptr(self.0.value_name).to_str().unwrap() } |
765 | } |
766 | |
767 | // rustdoc-stripper-ignore-next |
768 | /// Get nick corresponding to the value. |
769 | #[doc (alias = "get_nick" )] |
770 | pub fn nick(&self) -> &str { |
771 | unsafe { CStr::from_ptr(self.0.value_nick).to_str().unwrap() } |
772 | } |
773 | |
774 | // rustdoc-stripper-ignore-next |
775 | /// Convert flags value to a `Value`. |
776 | pub fn to_value(&self, flags: &FlagsClass) -> Value { |
777 | unsafe { |
778 | let mut v = Value::from_type_unchecked(flags.type_()); |
779 | gobject_ffi::g_value_set_flags(v.to_glib_none_mut().0, self.0.value); |
780 | v |
781 | } |
782 | } |
783 | |
784 | // rustdoc-stripper-ignore-next |
785 | /// Convert flags values from a `Value`. This returns all flags that are set. |
786 | pub fn from_value(value: &Value) -> Option<(FlagsClass, Vec<&FlagsValue>)> { |
787 | unsafe { |
788 | let flags_class = FlagsClass::with_type(value.type_())?; |
789 | let mut res = Vec::new(); |
790 | let f = gobject_ffi::g_value_get_flags(value.to_glib_none().0); |
791 | for v in flags_class.values() { |
792 | if v.value() & f != 0 { |
793 | res.push(&*(v as *const FlagsValue)); |
794 | } |
795 | } |
796 | Some((flags_class, res)) |
797 | } |
798 | } |
799 | } |
800 | |
801 | impl PartialEq for FlagsValue { |
802 | fn eq(&self, other: &Self) -> bool { |
803 | self.value().eq(&other.value()) |
804 | } |
805 | } |
806 | |
807 | impl Eq for FlagsValue {} |
808 | |
809 | // rustdoc-stripper-ignore-next |
810 | /// Builder for conveniently setting/unsetting flags and returning a `Value`. |
811 | /// |
812 | /// Example for getting a flags property, unsetting some flags and setting the updated flags on the |
813 | /// object again: |
814 | /// |
815 | /// ```ignore |
816 | /// let flags = obj.property("flags" ).unwrap(); |
817 | /// let flags_class = FlagsClass::new(flags.type_()).unwrap(); |
818 | /// let flags = flags_class.builder_with_value(flags).unwrap() |
819 | /// .unset_by_nick("some-flag" ) |
820 | /// .unset_by_nick("some-other-flag" ) |
821 | /// .build() |
822 | /// .unwrap(); |
823 | /// obj.set_property("flags" , &flags).unwrap(); |
824 | /// ``` |
825 | /// |
826 | /// If setting/unsetting any value fails, `build()` returns `None`. |
827 | #[must_use = "The builder must be built to be used" ] |
828 | pub struct FlagsBuilder<'a>(&'a FlagsClass, Option<Value>); |
829 | impl<'a> FlagsBuilder<'a> { |
830 | fn new(flags_class: &FlagsClass) -> FlagsBuilder { |
831 | let value = unsafe { Value::from_type_unchecked(flags_class.type_()) }; |
832 | FlagsBuilder(flags_class, Some(value)) |
833 | } |
834 | |
835 | fn with_value(flags_class: &FlagsClass, value: Value) -> FlagsBuilder { |
836 | FlagsBuilder(flags_class, Some(value)) |
837 | } |
838 | |
839 | // rustdoc-stripper-ignore-next |
840 | /// Set flags corresponding to integer value `f`. |
841 | pub fn set(mut self, f: u32) -> Self { |
842 | if let Some(value) = self.1.take() { |
843 | self.1 = self.0.set(value, f).ok(); |
844 | } |
845 | |
846 | self |
847 | } |
848 | |
849 | // rustdoc-stripper-ignore-next |
850 | /// Set flags corresponding to string name `name`. |
851 | pub fn set_by_name(mut self, name: &str) -> Self { |
852 | if let Some(value) = self.1.take() { |
853 | self.1 = self.0.set_by_name(value, name).ok(); |
854 | } |
855 | |
856 | self |
857 | } |
858 | |
859 | // rustdoc-stripper-ignore-next |
860 | /// Set flags corresponding to string nick `nick`. |
861 | pub fn set_by_nick(mut self, nick: &str) -> Self { |
862 | if let Some(value) = self.1.take() { |
863 | self.1 = self.0.set_by_nick(value, nick).ok(); |
864 | } |
865 | |
866 | self |
867 | } |
868 | |
869 | // rustdoc-stripper-ignore-next |
870 | /// Unsets flags corresponding to integer value `f`. |
871 | pub fn unset(mut self, f: u32) -> Self { |
872 | if let Some(value) = self.1.take() { |
873 | self.1 = self.0.unset(value, f).ok(); |
874 | } |
875 | |
876 | self |
877 | } |
878 | |
879 | // rustdoc-stripper-ignore-next |
880 | /// Unset flags corresponding to string name `name`. |
881 | pub fn unset_by_name(mut self, name: &str) -> Self { |
882 | if let Some(value) = self.1.take() { |
883 | self.1 = self.0.unset_by_name(value, name).ok(); |
884 | } |
885 | |
886 | self |
887 | } |
888 | |
889 | // rustdoc-stripper-ignore-next |
890 | /// Unset flags corresponding to string nick `nick`. |
891 | pub fn unset_by_nick(mut self, nick: &str) -> Self { |
892 | if let Some(value) = self.1.take() { |
893 | self.1 = self.0.unset_by_nick(value, nick).ok(); |
894 | } |
895 | |
896 | self |
897 | } |
898 | |
899 | // rustdoc-stripper-ignore-next |
900 | /// Converts to the final `Value`, unless any previous setting/unsetting of flags failed. |
901 | #[must_use = "Value returned from the builder should probably be used" ] |
902 | pub fn build(self) -> Option<Value> { |
903 | self.1 |
904 | } |
905 | } |
906 | |
907 | unsafe impl<'a, 'b> FromValue<'a> for Vec<&'b FlagsValue> { |
908 | type Checker = FlagsTypeChecker; |
909 | |
910 | unsafe fn from_value(value: &'a Value) -> Self { |
911 | let (_, v: Vec<&FlagsValue>) = FlagsValue::from_value(value).unwrap(); |
912 | // SAFETY: The enum class and its values live forever |
913 | std::mem::transmute(src:v) |
914 | } |
915 | } |
916 | |
917 | pub struct FlagsTypeChecker(); |
918 | unsafe impl ValueTypeChecker for FlagsTypeChecker { |
919 | type Error = InvalidFlagsError; |
920 | |
921 | fn check(value: &Value) -> Result<(), Self::Error> { |
922 | let t: Type = value.type_(); |
923 | if t.is_a(Type::FLAGS) { |
924 | Ok(()) |
925 | } else { |
926 | Err(InvalidFlagsError) |
927 | } |
928 | } |
929 | } |
930 | |
931 | // rustdoc-stripper-ignore-next |
932 | /// An error returned from the [`get`](struct.Value.html#method.get) function |
933 | /// on a [`Value`](struct.Value.html) for flags types. |
934 | #[derive (Clone, PartialEq, Eq, Debug)] |
935 | pub struct InvalidFlagsError; |
936 | |
937 | impl fmt::Display for InvalidFlagsError { |
938 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
939 | write!(f, "Value is not a flags" ) |
940 | } |
941 | } |
942 | |
943 | impl std::error::Error for InvalidFlagsError {} |
944 | |
945 | #[cfg (test)] |
946 | mod tests { |
947 | use super::*; |
948 | |
949 | #[test ] |
950 | fn test_flags() { |
951 | let flags = FlagsClass::new::<crate::BindingFlags>(); |
952 | let values = flags.values(); |
953 | let def1 = values |
954 | .iter() |
955 | .find(|v| v.name() == "G_BINDING_DEFAULT" ) |
956 | .unwrap(); |
957 | let def2 = flags.value_by_name("G_BINDING_DEFAULT" ).unwrap(); |
958 | assert!(ptr::eq(def1, def2)); |
959 | |
960 | let value = flags.to_value(0).unwrap(); |
961 | let values = value.get::<Vec<&FlagsValue>>().unwrap(); |
962 | assert_eq!(values.len(), 0); |
963 | |
964 | assert_eq!(def1.value(), crate::BindingFlags::DEFAULT.bits()); |
965 | } |
966 | } |
967 | |