| 1536 | |
| 1537 | #[pyfunction] |
| 1538 | fn _path_splitroot(path: OsPath, _vm: &VirtualMachine) -> (Wtf8Buf, Wtf8Buf) { |
| 1539 | let orig: Vec<_> = path.path.to_wide(); |
| 1540 | if orig.is_empty() { |
| 1541 | return (Wtf8Buf::new(), Wtf8Buf::new()); |
| 1542 | } |
| 1543 | let backslashed: Vec<_> = orig |
| 1544 | .iter() |
| 1545 | .copied() |
| 1546 | .map(|c| if c == b'/' as u16 { b'\\' as u16 } else { c }) |
| 1547 | .chain(core::iter::once(0)) // null-terminated |
| 1548 | .collect(); |
| 1549 | |
| 1550 | let mut end: *const u16 = core::ptr::null(); |
| 1551 | let hr = unsafe { |
| 1552 | windows_sys::Win32::UI::Shell::PathCchSkipRoot(backslashed.as_ptr(), &mut end) |
| 1553 | }; |
| 1554 | if hr >= 0 { |
| 1555 | assert!(!end.is_null()); |
| 1556 | let len: usize = unsafe { end.offset_from(backslashed.as_ptr()) } |
| 1557 | .try_into() |
| 1558 | .expect("len must be non-negative"); |
| 1559 | assert!( |
| 1560 | len < backslashed.len(), // backslashed is null-terminated |
| 1561 | "path: {:?} {} < {}", |
| 1562 | std::path::PathBuf::from(std::ffi::OsString::from_wide(&backslashed)), |
| 1563 | len, |
| 1564 | backslashed.len() |
| 1565 | ); |
| 1566 | if len != 0 { |
| 1567 | ( |
| 1568 | Wtf8Buf::from_wide(&orig[..len]), |
| 1569 | Wtf8Buf::from_wide(&orig[len..]), |
| 1570 | ) |
| 1571 | } else { |
| 1572 | (Wtf8Buf::from_wide(&orig), Wtf8Buf::new()) |
| 1573 | } |
| 1574 | } else { |
| 1575 | (Wtf8Buf::new(), Wtf8Buf::from_wide(&orig)) |
| 1576 | } |
| 1577 | } |
| 1578 | |
| 1579 | /// Normalize a wide-char path (faithful port of _Py_normpath_and_size). |
| 1580 | /// Uses lastC tracking like the C implementation. |