Skip to content

Instantly share code, notes, and snippets.

@NyxCode
Last active March 1, 2024 12:21
Show Gist options
  • Save NyxCode/bc0d2ac1b0af06a98e4795017926937b to your computer and use it in GitHub Desktop.
Save NyxCode/bc0d2ac1b0af06a98e4795017926937b to your computer and use it in GitHub Desktop.
/// Converts the given path into an absolute path by appending it to `std::env::current_dir()`.
/// All `.` and `..` components of the provided path are removed.
fn to_absolute_path(path: &Path) -> Result<PathBuf, ExportError> {
let path = if path.is_absolute() {
path.to_path_buf()
} else {
std::env::current_dir()?.join(path)
};
let mut out = Vec::new();
for comp in path.components() {
match comp {
Component::CurDir => (),
Component::ParentDir => {
out.pop().ok_or(CannotBeExported(
r#"The path provided with `#[ts(export_to = "..")]` is not valid"#,
))?;
}
comp => out.push(comp),
}
}
if !out.is_empty() {
Ok(out.iter().collect())
} else {
Ok(PathBuf::from("."))
}
}
// Construct a relative path from a provided base directory path to the provided path.
//
// Adapted from rustc's path_relative_from
// https://github.com/rust-lang/rust/blob/e1d0de82cc40b666b88d4a6d2c9dcbc81d7ed27f/src/librustc_back/rpath.rs#L116-L158
fn diff_paths<P, B>(path: P, base: B) -> Result<PathBuf, ExportError>
where
P: AsRef<Path>,
B: AsRef<Path>,
{
let path = to_absolute_path(path.as_ref())?;
let base = to_absolute_path(base.as_ref())?;
let mut ita = path.components();
let mut itb = base.components();
let mut comps: Vec<Component> = vec![];
loop {
match (ita.next(), itb.next()) {
(Some(Component::ParentDir | Component::CurDir), _)
| (_, Some(Component::ParentDir | Component::CurDir)) => {
unreachable!("The paths have been cleaned, no '.' or '..' components are present")
}
(None, None) => break,
(Some(a), None) => {
comps.push(a);
comps.extend(ita.by_ref());
break;
}
(None, Some(_)) => comps.push(Component::ParentDir),
(Some(a), Some(b)) if comps.is_empty() && a == b => (),
(Some(a), Some(_)) => {
comps.push(Component::ParentDir);
for _ in itb {
comps.push(Component::ParentDir);
}
comps.push(a);
comps.extend(ita.by_ref());
break;
}
}
}
Ok(comps.iter().collect())
}
@NyxCode
Copy link
Author

NyxCode commented Mar 1, 2024

  • Removed license note (it's already MIT)
  • inlined and simplify clean_path (we know that the provided path starts at the root)
  • Panic in diff_paths if "." is encountered (to_absolute_path makes sure no "." are present)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment