cap_primitives/fs/via_parent/
open_parent.rs1use crate::fs::{errors, open_dir, path_requires_dir, MaybeOwnedFile};
6use std::ffi::OsStr;
7use std::io;
8use std::path::{Component, Path};
9
10pub(super) fn open_parent<'path, 'borrow>(
16 start: MaybeOwnedFile<'borrow>,
17 path: &'path Path,
18) -> io::Result<(MaybeOwnedFile<'borrow>, &'path OsStr)> {
19 let (dirname, basename) = split_parent(path).ok_or_else(errors::no_such_file_or_directory)?;
20
21 let dir = if dirname.as_os_str().is_empty() {
22 start
23 } else {
24 MaybeOwnedFile::owned(open_dir(&start, dirname)?)
25 };
26
27 Ok((dir, basename.as_os_str()))
28}
29
30fn split_parent(path: &Path) -> Option<(&Path, Component<'_>)> {
41 if path.as_os_str().is_empty() {
42 return None;
43 }
44
45 if !path_requires_dir(path) {
46 let mut comps = path.components();
47 if let Some(p) = comps.next_back() {
48 match p {
49 Component::Normal(_) | Component::CurDir => return Some((comps.as_path(), p)),
50 _ => (),
51 }
52 }
53 }
54
55 Some((path, Component::CurDir))
56}
57
58#[test]
59fn split_parent_basics() {
60 assert_eq!(
61 split_parent(Path::new("foo/bar/qux")).unwrap(),
62 (
63 Path::new("foo/bar"),
64 Component::Normal(Path::new("qux").as_ref())
65 )
66 );
67 assert_eq!(
68 split_parent(Path::new("foo/bar")).unwrap(),
69 (
70 Path::new("foo"),
71 Component::Normal(Path::new("bar").as_ref())
72 )
73 );
74 assert_eq!(
75 split_parent(Path::new("foo")).unwrap(),
76 (Path::new(""), Component::Normal(Path::new("foo").as_ref()))
77 );
78}
79
80#[test]
81fn split_parent_special_cases() {
82 assert!(split_parent(Path::new("")).is_none());
83 assert_eq!(
84 split_parent(Path::new("foo/")).unwrap(),
85 (Path::new("foo"), Component::CurDir)
86 );
87 assert_eq!(
88 split_parent(Path::new("foo/.")).unwrap(),
89 (Path::new("foo"), Component::CurDir)
90 );
91 assert_eq!(
92 split_parent(Path::new(".")).unwrap(),
93 (Path::new(""), Component::CurDir)
94 );
95 assert_eq!(
96 split_parent(Path::new("..")).unwrap(),
97 (Path::new(".."), Component::CurDir)
98 );
99 assert_eq!(
100 split_parent(Path::new("../..")).unwrap(),
101 (Path::new("../.."), Component::CurDir)
102 );
103 assert_eq!(
104 split_parent(Path::new("../foo")).unwrap(),
105 (
106 Path::new(".."),
107 Component::Normal(Path::new("foo").as_ref())
108 )
109 );
110 assert_eq!(
111 split_parent(Path::new("foo/..")).unwrap(),
112 (Path::new("foo/.."), Component::CurDir)
113 );
114 assert_eq!(
115 split_parent(Path::new("/foo")).unwrap(),
116 (Path::new("/"), Component::Normal(Path::new("foo").as_ref()))
117 );
118 assert_eq!(
119 split_parent(Path::new("/foo/")).unwrap(),
120 (Path::new("/foo"), Component::CurDir)
121 );
122 assert_eq!(
123 split_parent(Path::new("/")).unwrap(),
124 (Path::new("/"), Component::CurDir)
125 );
126}