lance_io/object_store/providers/
local.rs1use std::sync::Arc;
5
6use crate::object_store::{
7 ObjectStore, ObjectStoreParams, ObjectStoreProvider, StorageOptions, DEFAULT_LOCAL_BLOCK_SIZE,
8 DEFAULT_LOCAL_IO_PARALLELISM, DEFAULT_MAX_IOP_SIZE,
9};
10use lance_core::error::Result;
11use lance_core::Error;
12use object_store::{local::LocalFileSystem, path::Path};
13use snafu::location;
14use url::Url;
15
16#[derive(Default, Debug)]
17pub struct FileStoreProvider;
18
19#[async_trait::async_trait]
20impl ObjectStoreProvider for FileStoreProvider {
21 async fn new_store(&self, base_path: Url, params: &ObjectStoreParams) -> Result<ObjectStore> {
22 let block_size = params.block_size.unwrap_or(DEFAULT_LOCAL_BLOCK_SIZE);
23 let storage_options = StorageOptions(params.storage_options.clone().unwrap_or_default());
24 let download_retry_count = storage_options.download_retry_count();
25 Ok(ObjectStore {
26 inner: Arc::new(LocalFileSystem::new()),
27 scheme: base_path.scheme().to_owned(),
28 block_size,
29 max_iop_size: *DEFAULT_MAX_IOP_SIZE,
30 use_constant_size_upload_parts: false,
31 list_is_lexically_ordered: false,
32 io_parallelism: DEFAULT_LOCAL_IO_PARALLELISM,
33 download_retry_count,
34 })
35 }
36
37 fn extract_path(&self, url: &Url) -> Result<Path> {
38 if let Ok(file_path) = url.to_file_path() {
39 if let Ok(path) = Path::from_absolute_path(&file_path) {
40 return Ok(path);
41 }
42 }
43
44 Path::parse(url.path()).map_err(|e| {
45 Error::invalid_input(
46 format!("Failed to parse path '{}': {}", url.path(), e),
47 location!(),
48 )
49 })
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use crate::object_store::uri_to_url;
56
57 use super::*;
58
59 #[test]
60 fn test_file_store_path() {
61 let provider = FileStoreProvider;
62
63 let cases = [
64 ("file:///", ""),
65 ("file:///usr/local/bin", "usr/local/bin"),
66 ("file-object-store:///path/to/file", "path/to/file"),
67 ("file:///path/to/foo/../bar", "path/to/bar"),
68 ];
69
70 for (uri, expected_path) in cases {
71 let url = uri_to_url(uri).unwrap();
72 let path = provider.extract_path(&url).unwrap();
73 assert_eq!(path.as_ref(), expected_path, "uri: '{}'", uri);
74 }
75 }
76
77 #[test]
78 #[cfg(windows)]
79 fn test_file_store_path_windows() {
80 let provider = FileStoreProvider;
81
82 let cases = [
83 (
84 "C:\\Users\\ADMINI~1\\AppData\\Local\\",
85 "C:/Users/ADMINI~1/AppData/Local",
86 ),
87 (
88 "C:\\Users\\ADMINI~1\\AppData\\Local\\..\\",
89 "C:/Users/ADMINI~1/AppData",
90 ),
91 ];
92
93 for (uri, expected_path) in cases {
94 let url = uri_to_url(uri).unwrap();
95 let path = provider.extract_path(&url).unwrap();
96 assert_eq!(path.as_ref(), expected_path);
97 }
98 }
99}