1use std::io::Read;
4use std::path::{Path, PathBuf};
5
6pub enum Input {
8 Text(String),
10 File(PathBuf),
12 Bytes(Vec<u8>),
14 Reader(Box<dyn Read + Send + Sync>),
16}
17
18impl std::fmt::Debug for Input {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 match self {
21 Input::Text(text) => f
22 .debug_struct("Input::Text")
23 .field("length", &text.len())
24 .finish(),
25 Input::File(path) => f.debug_struct("Input::File").field("path", path).finish(),
26 Input::Bytes(bytes) => f
27 .debug_struct("Input::Bytes")
28 .field("length", &bytes.len())
29 .finish(),
30 Input::Reader(_) => f.debug_struct("Input::Reader").finish(),
31 }
32 }
33}
34
35impl Input {
36 pub fn from_text(text: impl Into<String>) -> Self {
38 Input::Text(text.into())
39 }
40
41 pub fn from_file(path: impl AsRef<Path>) -> Self {
43 Input::File(path.as_ref().to_path_buf())
44 }
45
46 pub fn from_bytes(bytes: Vec<u8>) -> Self {
48 Input::Bytes(bytes)
49 }
50
51 pub fn from_reader(reader: impl Read + Send + Sync + 'static) -> Self {
53 Input::Reader(Box::new(reader))
54 }
55
56 pub(crate) fn into_bytes(self) -> Result<Vec<u8>, crate::api::Error> {
58 match self {
59 Input::Text(text) => Ok(text.into_bytes()),
60 Input::Bytes(bytes) => Ok(bytes),
61 Input::File(path) => std::fs::read(&path).map_err(|e| {
62 crate::api::Error::Infrastructure(format!(
63 "Failed to read file {}: {}",
64 path.display(),
65 e
66 ))
67 }),
68 Input::Reader(mut reader) => {
69 let mut buffer = Vec::new();
70 reader.read_to_end(&mut buffer).map_err(|e| {
71 crate::api::Error::Infrastructure(format!("Failed to read from reader: {e}"))
72 })?;
73 Ok(buffer)
74 }
75 }
76 }
77
78 pub(crate) fn into_text(self) -> Result<String, crate::api::Error> {
80 let bytes = self.into_bytes()?;
81 String::from_utf8(bytes)
82 .map_err(|e| crate::api::Error::Infrastructure(format!("Invalid UTF-8 encoding: {e}")))
83 }
84}