1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use glib::translate::*;
use std::mem;
use std::os::raw::c_void;

glib::wrapper! {
    /// A value containing a secret
    ///
    /// A #SecretValue contains a password or other secret value.
    ///
    /// Use [`get()`][Self::get()] to get the actual secret data, such as a password.
    /// The secret data is not necessarily null-terminated, unless the content type
    /// is "text/plain".
    ///
    /// Each #SecretValue has a content type. For passwords, this is `text/plain`.
    /// Use [`content_type()`][Self::content_type()] to look at the content type.
    ///
    /// #SecretValue is reference counted and immutable. The secret data is only
    /// freed when all references have been released via `Value::unref()`.
    #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
    pub struct Value(Shared<ffi::SecretValue>);

    match fn {
        ref => |ptr| ffi::secret_value_ref(ptr),
        // Manual
        unref => |ptr| ffi::secret_value_unref(ptr as *mut _ as *mut c_void),
        type_ => || ffi::secret_value_get_type(),
    }
}

impl Value {
    /// Create a #SecretValue for the secret data passed in.
    ///
    /// The secret data is copied into non-pageable 'secure' memory.
    ///
    /// If the length is less than zero, then @secret is assumed to be
    /// null-terminated.
    /// ## `secret`
    /// the secret data
    /// ## `length`
    /// the length of the data
    /// ## `content_type`
    /// the content type of the data
    ///
    /// # Returns
    ///
    /// the new #SecretValue
    #[doc(alias = "secret_value_new")]
    pub fn new(secret: &str, content_type: &str) -> Value {
        let length = secret.len() as isize;
        unsafe {
            from_glib_full(ffi::secret_value_new(
                secret.to_glib_none().0,
                length,
                content_type.to_glib_none().0,
            ))
        }
    }

    /// Get the secret data in the #SecretValue.
    ///
    /// The value is not necessarily null-terminated unless it was created with
    /// `Value::new()` or a null-terminated string was passed to
    /// `Value::new_full()`.
    ///
    /// # Returns
    ///
    /// the secret data
    #[doc(alias = "secret_value_get")]
    pub fn get(&self) -> Vec<u8> {
        unsafe {
            let mut length = mem::MaybeUninit::uninit();
            let ret = FromGlibContainer::from_glib_none_num(
                ffi::secret_value_get(self.to_glib_none().0, length.as_mut_ptr()),
                length.assume_init() as _,
            );
            ret
        }
    }

    /// Get the content type of the secret value, such as
    /// `text/plain`.
    ///
    /// # Returns
    ///
    /// the content type
    #[doc(alias = "secret_value_get_content_type")]
    #[doc(alias = "get_content_type")]
    pub fn content_type(&self) -> glib::GString {
        unsafe { from_glib_none(ffi::secret_value_get_content_type(self.to_glib_none().0)) }
    }

    /// Get the secret data in the #SecretValue if it contains a textual
    /// value.
    ///
    /// The content type must be `text/plain`.
    ///
    /// # Returns
    ///
    /// the content type
    #[doc(alias = "secret_value_get_text")]
    #[doc(alias = "get_text")]
    pub fn text(&self) -> Option<glib::GString> {
        unsafe { from_glib_none(ffi::secret_value_get_text(self.to_glib_none().0)) }
    }

    /// Unreference a #SecretValue and steal the secret data in
    /// #SecretValue as nonpageable memory.
    /// ## `length`
    /// the length of the secret
    ///
    /// # Returns
    ///
    /// a new password string stored in nonpageable memory
    ///   which must be freed with `password_free()` when done
    #[cfg(any(feature = "v0_19", feature = "dox"))]
    #[cfg_attr(feature = "dox", doc(cfg(feature = "v0_19")))]
    #[doc(alias = "secret_value_unref_to_password")]
    pub fn unref_to_password(&self) -> glib::GString {
        unsafe {
            let mut length = std::mem::MaybeUninit::uninit();
            let password =
                ffi::secret_value_unref_to_password(self.to_glib_none().0, length.as_mut_ptr());
            length.assume_init();

            from_glib_full(password)
        }
    }
}