1use std::path::{Path, PathBuf};
4
5#[must_use]
7pub fn hex_encode(bytes: &[u8]) -> String {
8 bytes
9 .iter()
10 .fold(String::with_capacity(bytes.len() * 2), |mut output, b| {
11 use std::fmt::Write;
12 let _ = write!(output, "{b:02x}");
13 output
14 })
15}
16
17pub fn resolve_relative(path: &Path, project_root: &Path) -> std::io::Result<PathBuf> {
22 if path.is_absolute() {
23 Ok(path.to_path_buf())
24 } else {
25 project_root.join(path).canonicalize()
26 }
27}
28
29#[cfg(test)]
30mod tests {
31 use super::{hex_encode, resolve_relative};
32 use std::path::Path;
33
34 #[test]
35 fn hex_encode_empty() {
36 assert_eq!(hex_encode(&[]), "");
37 }
38
39 #[test]
40 fn hex_encode_single_bytes() {
41 assert_eq!(hex_encode(&[0x00]), "00");
42 assert_eq!(hex_encode(&[0xff]), "ff");
43 assert_eq!(hex_encode(&[0xab, 0xcd, 0xef]), "abcdef");
44 }
45
46 #[test]
47 fn resolve_relative_passes_absolute_through() {
48 let abs = Path::new("/does/not/exist/absolute");
49 let resolved = resolve_relative(abs, Path::new("/tmp")).unwrap();
50 assert_eq!(resolved, abs);
51 }
52
53 #[test]
54 fn resolve_relative_joins_relative_and_canonicalizes() {
55 let cwd = std::env::current_dir().unwrap();
57 let resolved = resolve_relative(Path::new("."), &cwd).unwrap();
58 assert_eq!(resolved, cwd.canonicalize().unwrap());
60 }
61}