1use crate::bridge;
2use crate::error::Result;
3
4#[derive(Debug, Clone, PartialEq, Eq, Hash)]
5pub struct KeychainEntry {
6 account: String,
7 service: String,
8}
9
10impl KeychainEntry {
11 pub fn new(account: impl Into<String>, service: impl Into<String>) -> Self {
12 Self {
13 account: account.into(),
14 service: service.into(),
15 }
16 }
17
18 pub fn account(&self) -> &str {
19 &self.account
20 }
21
22 pub fn service(&self) -> &str {
23 &self.service
24 }
25
26 pub fn set(&self, password: &str) -> Result<()> {
27 Keychain::set(&self.account, &self.service, password)
28 }
29
30 pub fn get(&self) -> Result<String> {
31 Keychain::get(&self.account, &self.service)
32 }
33
34 pub fn delete(&self) -> Result<()> {
35 Keychain::delete(&self.account, &self.service)
36 }
37}
38
39pub struct Keychain;
40
41impl Keychain {
42 pub fn entry(account: impl Into<String>, service: impl Into<String>) -> KeychainEntry {
43 KeychainEntry::new(account, service)
44 }
45
46 pub fn set(account: &str, service: &str, password: &str) -> Result<()> {
47 let account = bridge::cstring(account)?;
48 let service = bridge::cstring(service)?;
49 let password = bridge::cstring(password)?;
50 let mut error = std::ptr::null_mut();
51 let status = unsafe {
52 bridge::security_keychain_set_password(
53 account.as_ptr(),
54 service.as_ptr(),
55 password.as_ptr(),
56 &mut error,
57 )
58 };
59 bridge::status_result("security_keychain_set_password", status, error)
60 }
61
62 pub fn get(account: &str, service: &str) -> Result<String> {
63 let account = bridge::cstring(account)?;
64 let service = bridge::cstring(service)?;
65 let mut status = 0;
66 let mut error = std::ptr::null_mut();
67 let raw = unsafe {
68 bridge::security_keychain_get_password(
69 account.as_ptr(),
70 service.as_ptr(),
71 &mut status,
72 &mut error,
73 )
74 };
75 bridge::required_string("security_keychain_get_password", raw, status, error)
76 }
77
78 pub fn delete(account: &str, service: &str) -> Result<()> {
79 let account = bridge::cstring(account)?;
80 let service = bridge::cstring(service)?;
81 let mut error = std::ptr::null_mut();
82 let status = unsafe {
83 bridge::security_keychain_delete_password(account.as_ptr(), service.as_ptr(), &mut error)
84 };
85 bridge::status_result("security_keychain_delete_password", status, error)
86 }
87
88 pub fn list_accounts(service: &str) -> Result<Vec<String>> {
89 let service = bridge::cstring(service)?;
90 let mut status = 0;
91 let mut error = std::ptr::null_mut();
92 let raw = unsafe {
93 bridge::security_keychain_list_accounts(service.as_ptr(), &mut status, &mut error)
94 };
95 bridge::required_json("security_keychain_list_accounts", raw, status, error)
96 }
97}