///|
extern "C" fn is_available_ffi() -> Int = "mb_safe_storage_is_available"
///|
#borrow(value)
extern "C" fn encrypt_ffi(value : Bytes) -> Bytes = "mb_safe_storage_encrypt"
///|
#borrow(value)
extern "C" fn decrypt_ffi(value : Bytes) -> Bytes = "mb_safe_storage_decrypt"
///|
extern "C" fn last_error_ffi() -> Bytes = "mb_safe_storage_last_error"
///|
extern "C" fn operation_ok_ffi() -> Int = "mb_safe_storage_operation_ok"
///|
fn error_message(default : String) -> String {
let message = @utf8.decode_lossy(last_error_ffi()[:])
if message.is_empty() {
default
} else {
message
}
}
///|
/// Returns whether OS-backed safe storage is available on this target.
pub fn is_available() -> Bool {
is_available_ffi() != 0
}
///|
/// Encrypts UTF-8 text using the current user's OS-backed secret store.
pub fn encrypt_string(value : String) -> Result[String, String] {
let encrypted = encrypt_ffi(@utf8.encode(value))
if operation_ok_ffi() == 0 {
Err(error_message("safe storage encryption failed"))
} else {
Ok(@base64.encode(encrypted))
}
}
///|
/// Decrypts a base64 payload produced by `encrypt_string`.
pub fn decrypt_string(value : String) -> Result[String, String] {
let encrypted = @base64.decode(value) catch {
_ => return Err("safe storage payload is not valid base64")
}
let decrypted = decrypt_ffi(encrypted)
if operation_ok_ffi() == 0 {
Err(error_message("safe storage decryption failed"))
} else {
Ok(@utf8.decode_lossy(decrypted[:]))
}
}