1use crate::result::Transcript;
10use transcribe_cpp_sys as sys;
11
12pub type Result<T> = std::result::Result<T, Error>;
14
15#[derive(Debug, thiserror::Error)]
21#[non_exhaustive]
22pub enum Error {
23 #[error("invalid argument: {0}")]
25 InvalidArgument(String),
26 #[error("not implemented by this model: {0}")]
28 NotImplemented(String),
29 #[error("model file not found: {0}")]
31 ModelFileNotFound(String),
32 #[error("model load failed: {0}")]
34 ModelLoad(String),
35 #[error("out of memory: {0}")]
37 OutOfMemory(String),
38 #[error("backend error: {0}")]
40 Backend(String),
41 #[error("unsupported request: {0}")]
44 Unsupported(String),
45 #[error("ABI struct-size mismatch: {0}")]
48 BadStructSize(String),
49 #[error("input too long: {0}")]
51 InputTooLong(String),
52 #[error("operation aborted: {message}")]
55 Aborted {
56 message: String,
57 partial: Option<Box<Transcript>>,
59 },
60 #[error("output truncated before end-of-stream: {message}")]
64 OutputTruncated {
65 message: String,
66 partial: Option<Box<Transcript>>,
68 },
69 #[error("native library version mismatch: {0}")]
72 VersionMismatch(String),
73 #[error("string contains an interior NUL byte: {0}")]
75 Nul(#[from] std::ffi::NulError),
76 #[error("model busy: {0}")]
83 Busy(String),
84 #[error("{0}")]
86 Other(String),
87}
88
89impl Error {
90 pub fn raw_status(&self) -> i32 {
93 use sys::transcribe_status as S;
94 let s = match self {
95 Error::InvalidArgument(_) => S::TRANSCRIBE_ERR_INVALID_ARG,
96 Error::NotImplemented(_) => S::TRANSCRIBE_ERR_NOT_IMPLEMENTED,
97 Error::ModelFileNotFound(_) => S::TRANSCRIBE_ERR_FILE_NOT_FOUND,
98 Error::ModelLoad(_) => S::TRANSCRIBE_ERR_GGUF,
99 Error::OutOfMemory(_) => S::TRANSCRIBE_ERR_OOM,
100 Error::Backend(_) => S::TRANSCRIBE_ERR_BACKEND,
101 Error::Unsupported(_) => S::TRANSCRIBE_ERR_UNSUPPORTED_TASK,
102 Error::BadStructSize(_) => S::TRANSCRIBE_ERR_BAD_STRUCT_SIZE,
103 Error::InputTooLong(_) => S::TRANSCRIBE_ERR_INPUT_TOO_LONG,
104 Error::Aborted { .. } => S::TRANSCRIBE_ERR_ABORTED,
105 Error::OutputTruncated { .. } => S::TRANSCRIBE_ERR_OUTPUT_TRUNCATED,
106 _ => S::TRANSCRIBE_OK,
107 };
108 s.0 as i32
109 }
110
111 pub fn partial(&self) -> Option<&Transcript> {
114 match self {
115 Error::Aborted { partial, .. } | Error::OutputTruncated { partial, .. } => {
116 partial.as_deref()
117 }
118 _ => None,
119 }
120 }
121}
122
123pub(crate) fn status_string(status: i32) -> String {
125 let ptr = unsafe { sys::transcribe_status_string(status) };
127 if ptr.is_null() {
128 return format!("status {status}");
129 }
130 unsafe { std::ffi::CStr::from_ptr(ptr) }
131 .to_string_lossy()
132 .into_owned()
133}
134
135pub(crate) fn error_for_status(status: sys::transcribe_status, context: &str) -> Error {
138 use sys::transcribe_status as S;
139 let code = status.0 as i32;
140 let msg = {
141 let s = status_string(code);
142 if context.is_empty() {
143 format!("{s} (status {code})")
144 } else {
145 format!("{context}: {s} (status {code})")
146 }
147 };
148 match status {
149 S::TRANSCRIBE_ERR_INVALID_ARG | S::TRANSCRIBE_ERR_SAMPLE_RATE => {
150 Error::InvalidArgument(msg)
151 }
152 S::TRANSCRIBE_ERR_NOT_IMPLEMENTED => Error::NotImplemented(msg),
153 S::TRANSCRIBE_ERR_FILE_NOT_FOUND => Error::ModelFileNotFound(msg),
154 S::TRANSCRIBE_ERR_GGUF
155 | S::TRANSCRIBE_ERR_UNSUPPORTED_ARCH
156 | S::TRANSCRIBE_ERR_UNSUPPORTED_VARIANT => Error::ModelLoad(msg),
157 S::TRANSCRIBE_ERR_OOM => Error::OutOfMemory(msg),
158 S::TRANSCRIBE_ERR_BACKEND => Error::Backend(msg),
159 S::TRANSCRIBE_ERR_UNSUPPORTED_LANGUAGE
160 | S::TRANSCRIBE_ERR_UNSUPPORTED_TASK
161 | S::TRANSCRIBE_ERR_UNSUPPORTED_TIMESTAMPS
162 | S::TRANSCRIBE_ERR_UNSUPPORTED_PNC
163 | S::TRANSCRIBE_ERR_UNSUPPORTED_ITN => Error::Unsupported(msg),
164 S::TRANSCRIBE_ERR_BAD_STRUCT_SIZE => Error::BadStructSize(msg),
165 S::TRANSCRIBE_ERR_INPUT_TOO_LONG => Error::InputTooLong(msg),
166 S::TRANSCRIBE_ERR_ABORTED => Error::Aborted {
167 message: msg,
168 partial: None,
169 },
170 S::TRANSCRIBE_ERR_OUTPUT_TRUNCATED => Error::OutputTruncated {
171 message: msg,
172 partial: None,
173 },
174 _ => Error::Other(msg),
175 }
176}
177
178pub(crate) fn check(status: sys::transcribe_status, context: &str) -> Result<()> {
180 if status == sys::transcribe_status::TRANSCRIBE_OK {
181 Ok(())
182 } else {
183 Err(error_for_status(status, context))
184 }
185}