diff --git a/src/bash.rs b/src/bash.rs index 42e329b..6f91d53 100644 --- a/src/bash.rs +++ b/src/bash.rs @@ -124,9 +124,9 @@ impl Bash { /// pub fn quote_vec<'a, S: ?Sized + Into>>(s: S) -> Vec { match s.into() { - Quotable::Bytes(bytes) => match bytes::escape_prepare(bytes) { + Quotable::Bytes(ref bytes) => match bytes::escape_prepare(bytes) { bytes::Prepared::Empty => vec![b'\'', b'\''], - bytes::Prepared::Inert => bytes.into(), + bytes::Prepared::Inert => bytes.clone().into_owned(), bytes::Prepared::Escape(esc) => { // This may be a pointless optimisation, but calculate the // memory needed to avoid reallocations as we construct the @@ -137,9 +137,9 @@ impl Bash { sout } }, - Quotable::Text(text) => match text::escape_prepare(text) { + Quotable::Text(ref text) => match text::escape_prepare(text) { text::Prepared::Empty => vec![b'\'', b'\''], - text::Prepared::Inert => text.into(), + text::Prepared::Inert => text.as_bytes().into(), text::Prepared::Escape(esc) => { // This may be a pointless optimisation, but calculate the // memory needed to avoid reallocations as we construct the @@ -170,9 +170,9 @@ impl Bash { /// pub fn quote_into_vec<'a, S: ?Sized + Into>>(s: S, sout: &mut Vec) { match s.into() { - Quotable::Bytes(bytes) => match bytes::escape_prepare(bytes) { + Quotable::Bytes(ref bytes) => match bytes::escape_prepare(bytes) { bytes::Prepared::Empty => sout.extend(b"''"), - bytes::Prepared::Inert => sout.extend(bytes), + bytes::Prepared::Inert => sout.extend(bytes.as_ref()), bytes::Prepared::Escape(esc) => { // This may be a pointless optimisation, but calculate the // memory needed to avoid reallocations as we construct the @@ -184,7 +184,7 @@ impl Bash { debug_assert_eq!(cap, sout.capacity()); // No reallocations. } }, - Quotable::Text(text) => match text::escape_prepare(text) { + Quotable::Text(ref text) => match text::escape_prepare(text) { text::Prepared::Empty => sout.extend(b"''"), text::Prepared::Inert => sout.extend(text.as_bytes()), text::Prepared::Escape(esc) => { diff --git a/src/fish.rs b/src/fish.rs index 673d315..fa9a82a 100644 --- a/src/fish.rs +++ b/src/fish.rs @@ -90,18 +90,18 @@ impl Fish { /// ``` pub fn quote_vec<'a, S: ?Sized + Into>>(s: S) -> Vec { match s.into() { - Quotable::Bytes(bytes) => match bytes::escape_prepare(bytes) { + Quotable::Bytes(ref bytes) => match bytes::escape_prepare(bytes) { bytes::Prepared::Empty => vec![b'\'', b'\''], - bytes::Prepared::Inert => bytes.into(), + bytes::Prepared::Inert => bytes.clone().into_owned(), bytes::Prepared::Escape(esc) => { let mut sout = Vec::with_capacity(esc.len() + 2); bytes::escape_chars(esc, &mut sout); // Do the work. sout } }, - Quotable::Text(text) => match text::escape_prepare(text) { + Quotable::Text(ref text) => match text::escape_prepare(text) { text::Prepared::Empty => vec![b'\'', b'\''], - text::Prepared::Inert => text.into(), + text::Prepared::Inert => text.as_bytes().into(), text::Prepared::Escape(esc) => { let mut sout = Vec::with_capacity(esc.len() + 2); text::escape_chars(esc, &mut sout); // Do the work. @@ -128,15 +128,15 @@ impl Fish { /// pub fn quote_into_vec<'a, S: ?Sized + Into>>(s: S, sout: &mut Vec) { match s.into() { - Quotable::Bytes(bytes) => match bytes::escape_prepare(bytes) { + Quotable::Bytes(ref bytes) => match bytes::escape_prepare(bytes) { bytes::Prepared::Empty => sout.extend(b"''"), - bytes::Prepared::Inert => sout.extend(bytes), + bytes::Prepared::Inert => sout.extend(bytes.as_ref()), bytes::Prepared::Escape(esc) => { sout.reserve(esc.len() + 2); bytes::escape_chars(esc, sout); // Do the work. } }, - Quotable::Text(text) => match text::escape_prepare(text) { + Quotable::Text(ref text) => match text::escape_prepare(text) { text::Prepared::Empty => sout.extend(b"''"), text::Prepared::Inert => sout.extend(text.as_bytes()), text::Prepared::Escape(esc) => { diff --git a/src/lib.rs b/src/lib.rs index fe8f86f..3d9a15a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ doc = include_str!("../README.md") )] +use std::borrow::Cow; use std::ffi::{OsStr, OsString}; use std::path::{Path, PathBuf}; @@ -111,41 +112,53 @@ pub enum Quotable<'a> { not(any(feature = "bash", feature = "fish", feature = "sh")), allow(unused) )] - Bytes(&'a [u8]), + Bytes(Cow<'a, [u8]>), #[cfg_attr( not(any(feature = "bash", feature = "fish", feature = "sh")), allow(unused) )] - Text(&'a str), + Text(Cow<'a, str>), +} + +impl From for Quotable<'static> { + fn from(source: u8) -> Quotable<'static> { + Quotable::Bytes(Cow::Owned(vec![source])) + } +} + +impl From for Quotable<'static> { + fn from(source: char) -> Quotable<'static> { + Quotable::Text(Cow::Owned(source.to_string())) + } } impl<'a> From<&'a [u8]> for Quotable<'a> { fn from(source: &'a [u8]) -> Quotable<'a> { - Quotable::Bytes(source) + Quotable::Bytes(Cow::Borrowed(source)) } } impl<'a, const N: usize> From<&'a [u8; N]> for Quotable<'a> { fn from(source: &'a [u8; N]) -> Quotable<'a> { - Quotable::Bytes(&source[..]) + Quotable::Bytes(Cow::Borrowed(&source[..])) } } impl<'a> From<&'a Vec> for Quotable<'a> { fn from(source: &'a Vec) -> Quotable<'a> { - Quotable::Bytes(source) + Quotable::Bytes(Cow::Borrowed(source)) } } impl<'a> From<&'a str> for Quotable<'a> { fn from(source: &'a str) -> Quotable<'a> { - Quotable::Text(source) + Quotable::Text(Cow::Borrowed(source)) } } impl<'a> From<&'a String> for Quotable<'a> { fn from(source: &'a String) -> Quotable<'a> { - Quotable::Text(source) + Quotable::Text(Cow::Borrowed(source)) } } diff --git a/src/sh.rs b/src/sh.rs index ef032f0..f96e98a 100644 --- a/src/sh.rs +++ b/src/sh.rs @@ -136,9 +136,10 @@ impl Sh { /// ``` /// pub fn quote_vec<'a, S: ?Sized + Into>>(s: S) -> Vec { - let bytes = match s.into() { - Quotable::Bytes(bytes) => bytes, - Quotable::Text(s) => s.as_bytes(), + let quotable = s.into(); + let bytes = match quotable { + Quotable::Bytes(ref bytes) => bytes.as_ref(), + Quotable::Text(ref text) => text.as_bytes(), }; match escape_prepare(bytes) { Prepared::Empty => vec![b'\'', b'\''], @@ -180,9 +181,10 @@ impl Sh { /// ``` /// pub fn quote_into_vec<'a, S: ?Sized + Into>>(s: S, sout: &mut Vec) { - let bytes = match s.into() { - Quotable::Bytes(bytes) => bytes, - Quotable::Text(s) => s.as_bytes(), + let quotable = s.into(); + let bytes = match quotable { + Quotable::Bytes(ref bytes) => bytes.as_ref(), + Quotable::Text(ref text) => text.as_bytes(), }; match escape_prepare(bytes) { Prepared::Empty => sout.extend(b"''"),