sakurs_core/api/
input.rs

1//! Input abstraction for unified API
2
3use std::io::Read;
4use std::path::{Path, PathBuf};
5
6/// Unified input abstraction for various data sources
7pub enum Input {
8    /// Direct text input
9    Text(String),
10    /// File path input
11    File(PathBuf),
12    /// Raw bytes input
13    Bytes(Vec<u8>),
14    /// Reader input (boxed for object safety)
15    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    /// Create input from text
37    pub fn from_text(text: impl Into<String>) -> Self {
38        Input::Text(text.into())
39    }
40
41    /// Create input from file path
42    pub fn from_file(path: impl AsRef<Path>) -> Self {
43        Input::File(path.as_ref().to_path_buf())
44    }
45
46    /// Create input from bytes
47    pub fn from_bytes(bytes: Vec<u8>) -> Self {
48        Input::Bytes(bytes)
49    }
50
51    /// Create input from reader
52    pub fn from_reader(reader: impl Read + Send + Sync + 'static) -> Self {
53        Input::Reader(Box::new(reader))
54    }
55
56    /// Convert input to bytes
57    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    /// Get text content from input
79    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}