--- title: "Filesystem and URI construction" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Filesystem and URI construction} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>") ``` The core package contract is a byte-oriented filesystem handle with explicit service selection. ```{r} library(Ropendal) # Local filesystem via constructor. root <- file.path(tempdir(), "ropendal-abstract-fs") unlink(root, recursive = TRUE) dir.create(root, recursive = TRUE) fs <- opendal("fs", root = root) # The same contract via URI. Put the local root in the query string so the # example is portable across POSIX and Windows path syntax. uri <- paste0("fs:///?root=", utils::URLencode(root, reserved = TRUE)) uri_fs <- opendal_uri(uri) isTRUE(identical(fs_info(uri_fs)$scheme, fs_info(fs)$scheme)) ``` ### Root-relative paths All paths are normalized to the handle root before any operation, so clients can use portable relative paths. ```{r} fs_write(fs, "a/b/c.bin", as.raw(c(1, 2, 3))) fs_read(fs, "a/b/c.bin") fs_stat(fs, "a/b/c.bin")$path ``` ### Range-heavy readers Index-heavy formats can build a small range request object and pass it to the same read verbs. This keeps Zarr-like chunk readers, FASTA indexes, and other binary table lookups on the byte-first API. ```{r} fs_write(fs, "chunks.bin", as.raw(1:8)) idx <- data.frame( path = "chunks.bin", offset = c(0, 4), size = c(4, 4), chunk = c("0.0", "0.1") ) req <- byte_ranges(idx$path, idx$offset, size = idx$size, id = idx$chunk) fs_read(fs, req) ``` ### Zarr-like byte stores A byte store is a prefix adapter over the same filesystem handle. It is not a full array implementation; it provides store-relative keys for metadata and chunks so higher-level packages can build Zarr-like readers on top. ```{r} store <- byte_store(fs, "toy.zarr") store_write(store, "zarr.json", charToRaw('{"zarr_format":3}')) store_write(store, "c/0/0", as.raw(c(1, 2, 3, 4))) store_list(store, recursive = TRUE) as.raw(store_read(store, "c/0/0")) # Add an explicit local full-object cache for repeated chunk reads. cached_store <- store_cache(store, tempfile("ropendal-cache-"), validate = "none") as.raw(collect_aio(store_read_aio(cached_store, "c/0/0"))) ``` ### Control knobs belong in handles `runtime_config()`, `layer_concurrent_limit()`, and `layer_timeout()` are attached at construction time so all operations share the same behavior. ```{r} fs <- opendal( "fs", root = root, runtime = runtime_config(threads = 2), layers = list( layer_concurrent_limit(2), layer_timeout(request_timeout = 30, io_timeout = 30) ) ) ``` ## Error values are first-class Failed object creation returns values instead of throwing, which keeps remote control flow explicit. ```{r} fs_write(fs, "a.bin", as.raw(1)) second <- fs_write(fs, "a.bin", as.raw(2)) is_error_value(second) if (is_error_value(second)) error_kind(second) else NULL ```