1use std::{
2 io::{self, ErrorKind},
3 path::{Path, PathBuf},
4};
5
6use anyhow::{Context, Result, anyhow};
7use turbo_tasks::ResolvedVc;
8
9use crate::{DiskFileSystem, FileSystemPath};
10
11pub fn extract_disk_access<T>(value: io::Result<T>, path: &Path) -> Result<Option<T>> {
15 match value {
16 Ok(v) => Ok(Some(v)),
17 Err(e) if matches!(e.kind(), ErrorKind::NotFound | ErrorKind::InvalidFilename) => Ok(None),
18 Err(e) => Err(anyhow!(e).context(format!("reading file {}", path.display()))),
20 }
21}
22
23pub async fn uri_from_file(root: FileSystemPath, path: Option<&str>) -> Result<String> {
24 let root_fs = root.fs;
25 let root_fs = &*ResolvedVc::try_downcast_type::<DiskFileSystem>(root_fs)
26 .context("Expected root to have a DiskFileSystem")?
27 .await?;
28
29 let path = match path {
30 Some(path) => root.join(path)?,
31 None => root,
32 };
33
34 Ok(uri_from_path_buf(root_fs.to_sys_path(&path)))
35}
36
37#[cfg(not(target_os = "windows"))]
38pub fn uri_from_path_buf(sys_path: PathBuf) -> String {
39 use turbo_unix_path::sys_to_unix;
40 let sys_path = sys_path.to_string_lossy();
41
42 format!(
43 "file://{}",
44 sys_to_unix(&sys_path)
45 .split('/')
46 .map(|s| urlencoding::encode(s))
47 .collect::<Vec<_>>()
48 .join("/")
49 )
50}
51
52#[cfg(target_os = "windows")]
53pub fn uri_from_path_buf(sys_path: PathBuf) -> String {
54 let raw_path = sys_path.to_string_lossy().to_string();
55 let normalized_path = raw_path.replace('\\', "/");
56
57 let mut segments = normalized_path.split('/');
58
59 let first = segments.next().unwrap_or_default(); let encoded_path = std::iter::once(first.to_string()) .chain(segments.map(|s| urlencoding::encode(s).into_owned()))
62 .collect::<Vec<_>>()
63 .join("/");
64
65 format!("file:///{}", encoded_path)
66}