Skip to content

Commit 6accdd5

Browse files
committed
refactor utf8 path assertions with camino
1 parent 0616bdc commit 6accdd5

5 files changed

Lines changed: 32 additions & 12 deletions

File tree

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ tracing = "0.1.41"
8585
simd-json = { version = "0.17.0", features = ["serde_impl", "runtime-detection"], default-features = false }
8686

8787
cfg-if = "1.0"
88+
camino = "1.2.1"
8889
dunce = "1.0.5" # Normalize Windows paths to the most compatible format, avoiding UNC where possible
8990
indexmap = { version = "2.12.0", features = ["serde"] }
9091
json-strip-comments = "3.0.1"

src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ use crate::{
9090
cache::{Cache, CachedPath},
9191
context::ResolveContext as Ctx,
9292
package_json::JSONMap,
93-
path::{path_to_str, PathUtil, SLASH_START},
93+
path::{path_to_str, path_to_utf8, PathUtil, SLASH_START},
9494
specifier::Specifier,
9595
tsconfig::{ExtendsField, ProjectReference, TsConfig},
9696
};
@@ -691,7 +691,7 @@ impl<Fs: FileSystem + Send + Sync> ResolverGeneric<Fs> {
691691
if ctx.fully_specified {
692692
return Ok(None);
693693
}
694-
let path = path_to_str(path.path());
694+
let path = path_to_utf8(path.path()).as_str();
695695
// 8 is wild guess for max extension length
696696
let mut path_with_extension_buffer = String::with_capacity(path.len() + 8);
697697
path_with_extension_buffer.push_str(path);
@@ -1332,7 +1332,7 @@ impl<Fs: FileSystem + Send + Sync> ResolverGeneric<Fs> {
13321332
Cow::Borrowed(alias_value)
13331333
} else {
13341334
let normalized = alias_path.normalize_with(tail);
1335-
Cow::Owned(path_to_str(&normalized).to_string())
1335+
Cow::Owned(path_to_utf8(&normalized).as_str().to_string())
13361336
}
13371337
};
13381338

@@ -1397,14 +1397,14 @@ impl<Fs: FileSystem + Send + Sync> ResolverGeneric<Fs> {
13971397
// Create a meaningful error message.
13981398
let dir = path.parent().unwrap().to_path_buf();
13991399
let filename_without_extension = Path::new(filename).with_extension("");
1400-
let filename_without_extension = path_to_str(&filename_without_extension);
1400+
let filename_without_extension = path_to_utf8(&filename_without_extension).as_str();
14011401
let files = extensions
14021402
.iter()
14031403
.map(|ext| format!("{filename_without_extension}{ext}"))
14041404
.collect::<Vec<_>>()
14051405
.join(",");
14061406
Err(ResolveError::ExtensionAlias(
1407-
filename.to_str().expect("path should be UTF-8").to_string(),
1407+
path_to_utf8(Path::new(filename)).as_str().to_string(),
14081408
files,
14091409
dir,
14101410
))

src/path.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,16 @@
55
//! * [normalize_path](https://docs.rs/normalize-path)
66
use std::path::{Component, Path, PathBuf};
77

8+
use camino::Utf8Path;
9+
810
pub const SLASH_START: &[char; 2] = &['/', '\\'];
911

12+
pub fn path_to_utf8(path: &Path) -> &Utf8Path {
13+
Utf8Path::from_path(path).expect("path should be UTF-8")
14+
}
15+
1016
pub fn path_to_str(path: &Path) -> &str {
11-
path.to_str().expect("path should be UTF-8")
17+
path_to_utf8(path).as_str()
1218
}
1319

1420
/// Extension trait to add path normalization to std's [`Path`].

src/tsconfig.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use indexmap::IndexMap;
88
use rustc_hash::FxHasher;
99
use serde::Deserialize;
1010

11-
use crate::path::{path_to_str, PathUtil};
11+
use crate::path::{path_to_utf8, PathUtil};
1212

1313
pub type CompilerOptionsPathsMap = IndexMap<String, Vec<String>, BuildHasherDefault<FxHasher>>;
1414

@@ -78,7 +78,7 @@ pub struct ProjectReference {
7878
}
7979

8080
impl TsConfig {
81-
#[cfg_attr(feature="enable_instrument", tracing::instrument(level=tracing::Level::DEBUG, skip_all, fields(path = path_to_str(path))))]
81+
#[cfg_attr(feature="enable_instrument", tracing::instrument(level=tracing::Level::DEBUG, skip_all, fields(path = path_to_utf8(path).as_str())))]
8282
pub fn parse(root: bool, path: &Path, json: &mut str) -> Result<Self, serde_json::Error> {
8383
_ = json_strip_comments::strip(json);
8484
if json.trim().is_empty() {
@@ -121,12 +121,14 @@ impl TsConfig {
121121
}
122122
}
123123

124-
let mut p = path_to_str(&self.compiler_options.paths_base).to_string();
124+
let mut p = path_to_utf8(&self.compiler_options.paths_base)
125+
.as_str()
126+
.to_string();
125127
Self::substitute_template_variable(&dir, &mut p);
126128
self.compiler_options.paths_base = p.into();
127129

128130
if let Some(base_url) = self.compiler_options.base_url.as_mut() {
129-
let mut p = path_to_str(base_url).to_string();
131+
let mut p = path_to_utf8(base_url).as_str().to_string();
130132
Self::substitute_template_variable(&dir, &mut p);
131133
*base_url = p.into();
132134
}
@@ -258,9 +260,13 @@ impl TsConfig {
258260
fn substitute_template_variable(directory: &Path, path: &mut String) {
259261
if let Some(stripped_path) = path.strip_prefix(TEMPLATE_VARIABLE) {
260262
if let Some(unleashed_path) = stripped_path.strip_prefix("/") {
261-
*path = path_to_str(&directory.join(unleashed_path)).to_string();
263+
*path = path_to_utf8(&directory.join(unleashed_path))
264+
.as_str()
265+
.to_string();
262266
} else {
263-
*path = path_to_str(&directory.join(stripped_path)).to_string();
267+
*path = path_to_utf8(&directory.join(stripped_path))
268+
.as_str()
269+
.to_string();
264270
}
265271
}
266272
}

0 commit comments

Comments
 (0)