summaryrefslogtreecommitdiffstats
path: root/src/poem/recite.rs
diff options
context:
space:
mode:
authorRory Dudley2024-04-06 23:32:30 -0600
committerRory Dudley2024-04-06 23:32:30 -0600
commitf5db8d64828db756b80b6022322265a2b4f1c11b (patch)
tree68555331ad4dcab6c571c4016c1e8baa3a351ae7 /src/poem/recite.rs
parent1415c8f9b89699000ef8d864ff8f0e1bebca4a5f (diff)
downloaddwarvish-f5db8d64828db756b80b6022322265a2b4f1c11b.tar.gz
Capture STDOUT as bytes, and convert to string when necessary
Previously, the recite() function created the 'out' variable, which was a String, that got passed to the various incant functions, in order to capture STDOUT in certain situations. In cases where STDOUT was captured, it was first converted to a String, and then appended to the 'out' variable, by means of String::from_utf8_lossy(). This works for basic text, however, does NOT work for binary data. This becomes problematic, when for example, downling a tar file with curl/wget, that is then piped ('|') to the tar program. Using from_utf8_lossy() in this case can corrupt the tar file. This patch makes it so that out is stored as bytes by default, and only converted to a String when necessary.
Diffstat (limited to 'src/poem/recite.rs')
-rw-r--r--src/poem/recite.rs26
1 files changed, 18 insertions, 8 deletions
diff --git a/src/poem/recite.rs b/src/poem/recite.rs
index 4038e37..60b7857 100644
--- a/src/poem/recite.rs
+++ b/src/poem/recite.rs
@@ -4,6 +4,7 @@ use crate::compose::Environment;
use crate::path;
use crate::poem::anthology;
use crate::poem::elements::rune::Rune;
+use crate::poem::elements::stanza::Stanza;
use std::env;
use std::{
io,
@@ -11,16 +12,16 @@ use std::{
};
pub trait Reciteable {
- fn recite(&self, env: &mut Environment, stdout: Option<bool>) -> Result<String, io::Error>;
+ fn recite(&self, env: &mut Environment, stdout: Option<bool>) -> Result<Vec<u8>, io::Error>;
}
impl Reciteable for Poem {
- fn recite(&self, env: &mut Environment, stdout: Option<bool>) -> Result<String, io::Error> {
+ fn recite(&self, env: &mut Environment, stdout: Option<bool>) -> Result<Vec<u8>, io::Error> {
// Should we print to stdout or always capture it
let stdout = stdout.unwrap_or(true);
// Variable for storing the output of a piped verse
- let mut out: String = String::new();
+ let mut out: Vec<u8> = Vec::new();
// Keep track of pids for background processes
let mut pids: Arc<Mutex<Vec<i32>>> = Arc::new(Mutex::new(Vec::new()));
@@ -64,7 +65,7 @@ impl Reciteable for Poem {
// Run interal poems
let v = verse.clone();
- let mut new_stanza = None;
+ let mut new_stanza: Option<Stanza> = None;
if verse.poems() {
// Collect all the words that have vertical tabs
let mut wordp_indicies = vec![];
@@ -93,7 +94,17 @@ impl Reciteable for Poem {
Some(poem) => poem,
None => break, // TODO: Return an error
};
- let out = poem.recite(env, Some(false))?;
+ let mut out = poem.recite(env, Some(false))?;
+ match out.last() {
+ Some(last) => {
+ if *last == b'\n' {
+ out.remove(out.len() - 1);
+ }
+ }
+ None => {}
+ }
+
+ let out = String::from_utf8_lossy(&out);
if out.contains("\n") && index.is_none() {
let mut out = out.split("\n");
let next = out.next().unwrap_or("").trim();
@@ -112,9 +123,8 @@ impl Reciteable for Poem {
left.append(&mut right);
new_stanza = Some(left.clone());
} else {
- *wordp = wordp.replacen("\x0b", out.as_str(), 1).to_string();
+ *wordp = wordp.replacen("\x0b", &out, 1).to_string();
}
- *wordp = wordp.replacen("\x0b", out.as_str(), 1).to_string();
}
j += 1;
}
@@ -190,6 +200,6 @@ impl Reciteable for Poem {
// If we've successfully exited the loop, then all verses were properly
// recited
- Ok(out.trim().to_string())
+ Ok(out)
}
}