Async WebDAV client SDK for Ferro servers, with optional C-FFI bindings for mobile platforms (Swift/Kotlin).
Type Description
FerroClientAsync WebDAV client
FerroFileEntryFile metadata returned by list operations
Feature Default Description
ffino C-compatible FFI bindings for mobile (Swift/Kotlin)
use ferro_client::FerroClient;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = FerroClient::new("https://ferro.example.com", "my-token");
let info = client.test_connection().await?;
println!("Server has {} root entries", info.root_entries);
let files = client.list("/").await?;
for file in &files {
println!("{} ({} bytes)", file.name, file.size);
}
client.put_text("/hello.txt", "Hello, Ferro!").await?;
let content = client.get_text("/hello.txt").await?;
println!("{}", content);
client.create_directory("/documents").await?;
client.move_item("/hello.txt", "/documents/hello.txt").await?;
client.copy("/documents/hello.txt", "/documents/hello-backup.txt").await?;
client.delete("/documents/hello-backup.txt").await?;
Ok(())
}
Enable the ffi feature for C-compatible bindings:
[dependencies]
ferro-client = { version = "0.1", features = ["ffi"] }
Function Description
ferro_client_new(url, token)Create a client handle
ferro_client_free(handle)Destroy a client handle
ferro_test_connection(handle)Test server connection
let handle = ferro_client_new("https://ferro.example.com", "my-token")
defer { ferro_client_free(handle) }
let result = ferro_test_connection(handle)
if result == .Success {
print("Connected!")
}
val handle = ferro_client_new("https://ferro.example.com", "my-token")
try {
val result = ferro_test_connection(handle)
if (result == FerroResult.Success) {
println("Connected!")
}
} finally {
ferro_client_free(handle)
}
All FFI pointer returns must be freed with their corresponding _free function
String pointers are null-terminated UTF-8
Client handles are not thread-safe; use one per thread or synchronize externally