summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs8
-rw-r--r--src/path_list_editor.rs16
-rw-r--r--src/run.rs15
-rw-r--r--src/util/mod.rs1
-rw-r--r--src/util/path_list.rs52
5 files changed, 69 insertions, 23 deletions
diff --git a/src/lib.rs b/src/lib.rs
index c35c0ea..4815653 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -7,6 +7,8 @@
//! The crate is used by the main `repo2markdown` binary and by helper binaries such as
//! `r2md-fence`, `r2md-append`, `r2md-prepend`, and `r2md-remove`.
+mod util;
+
pub mod fence_wrapper;
pub mod fenced_md_generator;
pub mod logger;
@@ -14,4 +16,8 @@ pub mod md_generator;
pub mod normalizer;
pub mod path_list_editor;
pub mod renderer;
-mod util;
+
+/// Utilities for working with null-separated path lists.
+pub mod path_list {
+ pub use crate::util::path_list::paths_from_null_separated_bytes;
+}
diff --git a/src/path_list_editor.rs b/src/path_list_editor.rs
index a740bf2..bdd6982 100644
--- a/src/path_list_editor.rs
+++ b/src/path_list_editor.rs
@@ -9,13 +9,13 @@
use std::{
collections::HashSet,
- ffi::{OsStr, OsString},
+ ffi::OsString,
io::{Read, Write},
os::unix::ffi::OsStrExt,
- path::{Path, PathBuf},
+ path::PathBuf,
};
-use crate::normalizer::Normalizer;
+use crate::{normalizer::Normalizer, util::path_list::paths_from_null_separated_bytes};
const NUL: &[u8] = b"\0";
@@ -117,14 +117,10 @@ pub fn remove_paths<R: Read, W: Write>(
.iter()
.map(|path| normalizer.normalize(path))
.collect::<Result<HashSet<_>, _>>()?;
- for segment in input_buf.split(|b| *b == 0) {
- if segment.is_empty() {
- continue;
- }
- let os_string_segment = OsStr::from_bytes(segment);
- let normalized_path = normalizer.normalize(Path::new(os_string_segment))?;
+ for path in paths_from_null_separated_bytes(&input_buf) {
+ let normalized_path = normalizer.normalize(path)?;
if !unwanted_paths.contains(&normalized_path) {
- output.write_all(segment)?;
+ output.write_all(path.as_os_str().as_bytes())?;
output.write_all(NUL)?;
}
}
diff --git a/src/run.rs b/src/run.rs
index 5b1a790..183ce6b 100644
--- a/src/run.rs
+++ b/src/run.rs
@@ -1,13 +1,8 @@
-use std::{
- ffi::OsStr,
- io::{Read, Write},
- os::unix::ffi::OsStrExt,
- path::Path,
-};
+use std::io::{Read, Write};
use repo2markdown::{
fenced_md_generator::generate_fenced_markdown, logger::Logger,
- md_generator::generate_markdown_from_paths,
+ md_generator::generate_markdown_from_paths, path_list::paths_from_null_separated_bytes,
};
use crate::cli::Cli;
@@ -21,11 +16,7 @@ pub fn run<R: Read, W: Write>(
let mut input_buf = Vec::new();
input.read_to_end(&mut input_buf)?;
- let paths: Vec<&Path> = input_buf
- .split(|b| *b == 0)
- .filter(|bytes| !bytes.is_empty())
- .map(|bytes| Path::new(OsStr::from_bytes(bytes)))
- .collect();
+ let paths = paths_from_null_separated_bytes(&input_buf);
if cli.fenced {
generate_fenced_markdown(
diff --git a/src/util/mod.rs b/src/util/mod.rs
index 24ba6fc..eda8605 100644
--- a/src/util/mod.rs
+++ b/src/util/mod.rs
@@ -1,3 +1,4 @@
pub mod fence;
pub mod language;
pub mod path_display;
+pub mod path_list;
diff --git a/src/util/path_list.rs b/src/util/path_list.rs
new file mode 100644
index 0000000..88f43b9
--- /dev/null
+++ b/src/util/path_list.rs
@@ -0,0 +1,52 @@
+//! Null-separated path-list parsing helpers.
+
+use std::{ffi::OsStr, os::unix::ffi::OsStrExt, path::Path};
+
+/// Parses a NUL-separated path list into borrowed paths.
+///
+/// Empty segments are ignored. Returned paths borrow from `bytes`.
+pub fn paths_from_null_separated_bytes(bytes: &[u8]) -> Vec<&Path> {
+ bytes
+ .split(|byte| *byte == 0)
+ .filter(|segment| !segment.is_empty())
+ .map(|segment| Path::new(OsStr::from_bytes(segment)))
+ .collect()
+}
+
+#[cfg(test)]
+mod tests {
+ use std::path::Path;
+
+ use super::paths_from_null_separated_bytes;
+
+ #[test]
+ fn paths_from_null_separated_bytes_returns_empty_list_for_empty_input() {
+ let paths = paths_from_null_separated_bytes(b"");
+
+ assert!(paths.is_empty());
+ }
+
+ #[test]
+ fn paths_from_null_separated_bytes_ignores_empty_segments() {
+ let paths = paths_from_null_separated_bytes(b"\0a.rs\0\0b.rs\0");
+
+ assert_eq!(paths, vec![Path::new("a.rs"), Path::new("b.rs")]);
+ }
+
+ #[test]
+ fn paths_from_null_separated_bytes_accepts_final_path_without_trailing_nul() {
+ let paths = paths_from_null_separated_bytes(b"a.rs\0b.rs");
+
+ assert_eq!(paths, vec![Path::new("a.rs"), Path::new("b.rs")]);
+ }
+
+ #[test]
+ fn paths_from_null_separated_bytes_preserves_order() {
+ let paths = paths_from_null_separated_bytes(b"b.rs\0a.rs\0c.rs\0");
+
+ assert_eq!(
+ paths,
+ vec![Path::new("b.rs"), Path::new("a.rs"), Path::new("c.rs")]
+ );
+ }
+}