use std::io::Read;
pub enum StdinData {
Bytes(Vec<u8>),
Reader(Box<dyn Read + Send + Sync + 'static>),
}
impl StdinData {
pub fn from_reader<R: Read + Send + Sync + 'static>(reader: R) -> Self {
Self::Reader(Box::new(reader))
}
pub fn is_reusable(&self) -> bool {
matches!(self, Self::Bytes(_))
}
}
impl std::fmt::Debug for StdinData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Bytes(b) => f
.debug_struct("Bytes")
.field("len", &b.len())
.finish(),
Self::Reader(_) => f.debug_struct("Reader").finish_non_exhaustive(),
}
}
}
impl From<Vec<u8>> for StdinData {
fn from(v: Vec<u8>) -> Self {
Self::Bytes(v)
}
}
impl From<&[u8]> for StdinData {
fn from(s: &[u8]) -> Self {
Self::Bytes(s.to_vec())
}
}
impl From<&Vec<u8>> for StdinData {
fn from(v: &Vec<u8>) -> Self {
Self::Bytes(v.clone())
}
}
impl From<String> for StdinData {
fn from(s: String) -> Self {
Self::Bytes(s.into_bytes())
}
}
impl From<&str> for StdinData {
fn from(s: &str) -> Self {
Self::Bytes(s.as_bytes().to_vec())
}
}
impl From<&String> for StdinData {
fn from(s: &String) -> Self {
Self::Bytes(s.as_bytes().to_vec())
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Cursor;
#[test]
fn from_vec_u8() {
let data: StdinData = vec![1, 2, 3].into();
assert!(data.is_reusable());
match data {
StdinData::Bytes(b) => assert_eq!(b, vec![1, 2, 3]),
_ => panic!("expected Bytes"),
}
}
#[test]
fn from_byte_slice() {
let data: StdinData = (&b"hello"[..]).into();
match data {
StdinData::Bytes(b) => assert_eq!(b, b"hello"),
_ => panic!("expected Bytes"),
}
}
#[test]
fn from_string() {
let data: StdinData = String::from("hello").into();
match data {
StdinData::Bytes(b) => assert_eq!(b, b"hello"),
_ => panic!("expected Bytes"),
}
}
#[test]
fn from_str() {
let data: StdinData = "hello".into();
match data {
StdinData::Bytes(b) => assert_eq!(b, b"hello"),
_ => panic!("expected Bytes"),
}
}
#[test]
fn from_reader_marks_one_shot() {
let data = StdinData::from_reader(Cursor::new(vec![1, 2, 3]));
assert!(!data.is_reusable());
}
#[test]
fn debug_impl_redacts_reader_contents() {
let bytes_dbg = format!("{:?}", StdinData::Bytes(vec![0; 100]));
assert!(bytes_dbg.contains("100"));
let reader_dbg = format!(
"{:?}",
StdinData::from_reader(Cursor::new(vec![0u8; 100]))
);
assert!(reader_dbg.contains("Reader"));
assert!(!reader_dbg.contains("100"));
}
}