mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-09-24 21:40:48 +02:00
fix(fs): map open options to valid Android modes (#3624)
In plugins/fs/src/lib.rs OpenOptions::android_mode, the mode was built by
concatenating r/w/t/a, so open(url, {append: true}) (read defaults to
true) produced "ra" and write+truncate+append "wta", which
ParcelFileDescriptor.parseMode / ContentResolver reject.
The options now map to r, w, wt, wa, rw or rwt. append wins over the
default read (no read+append mode exists). create/createNew still have no
Android equivalent (documented on the function). Unit tests for the
mapping, compiled on the host with cfg(test).
This commit is contained in:
+51
-17
@@ -361,24 +361,23 @@ impl std::os::unix::fs::OpenOptionsExt for OpenOptions {
|
||||
}
|
||||
|
||||
impl OpenOptions {
|
||||
#[cfg(target_os = "android")]
|
||||
fn android_mode(&self) -> String {
|
||||
let mut mode = String::new();
|
||||
|
||||
if self.read {
|
||||
mode.push('r');
|
||||
/// The mode passed to `ContentResolver.openAssetFileDescriptor` / `ParcelFileDescriptor.parseMode`,
|
||||
/// which only accept `r`, `w`, `wt`, `wa`, `rw` and `rwt`.
|
||||
///
|
||||
/// `create` and `create_new` have no equivalent: whether a missing file is created
|
||||
/// depends on the content provider.
|
||||
#[cfg(any(target_os = "android", test))]
|
||||
fn android_mode(&self) -> &'static str {
|
||||
match (self.read, self.write || self.append) {
|
||||
(_, false) => "r",
|
||||
// there is no read + append mode, and `read` defaults to `true` from JavaScript:
|
||||
// honor the explicit append
|
||||
(_, true) if self.append => "wa",
|
||||
(true, true) if self.truncate => "rwt",
|
||||
(true, true) => "rw",
|
||||
(false, true) if self.truncate => "wt",
|
||||
(false, true) => "w",
|
||||
}
|
||||
if self.write {
|
||||
mode.push('w');
|
||||
}
|
||||
if self.truncate {
|
||||
mode.push('t');
|
||||
}
|
||||
if self.append {
|
||||
mode.push('a');
|
||||
}
|
||||
|
||||
mode
|
||||
}
|
||||
}
|
||||
|
||||
@@ -630,3 +629,38 @@ pub fn init<R: Runtime>() -> TauriPlugin<R, Option<config::Config>> {
|
||||
})
|
||||
.build()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::OpenOptions;
|
||||
|
||||
#[test]
|
||||
fn android_modes_are_valid() {
|
||||
let mode = |json: &str| {
|
||||
serde_json::from_str::<OpenOptions>(json)
|
||||
.unwrap()
|
||||
.android_mode()
|
||||
};
|
||||
|
||||
// `read` defaults to true when deserialized
|
||||
assert_eq!(mode(r#"{}"#), "r");
|
||||
assert_eq!(mode(r#"{ "read": false }"#), "r");
|
||||
assert_eq!(mode(r#"{ "write": true }"#), "rw");
|
||||
assert_eq!(mode(r#"{ "write": true, "truncate": true }"#), "rwt");
|
||||
assert_eq!(mode(r#"{ "append": true }"#), "wa");
|
||||
assert_eq!(mode(r#"{ "read": false, "write": true }"#), "w");
|
||||
assert_eq!(
|
||||
mode(r#"{ "read": false, "write": true, "truncate": true }"#),
|
||||
"wt"
|
||||
);
|
||||
assert_eq!(mode(r#"{ "read": false, "append": true }"#), "wa");
|
||||
assert_eq!(
|
||||
mode(r#"{ "read": false, "write": true, "truncate": true, "append": true }"#),
|
||||
"wa"
|
||||
);
|
||||
assert_eq!(
|
||||
mode(r#"{ "read": false, "write": true, "create": true }"#),
|
||||
"w"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user