translation/
translation_error.rs1use std::error::Error;
2use std::fmt;
3
4use crate::ffi;
5
6const FAILURE_REASON_DELIMITER: &str = "";
7
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum TranslationError {
11 InvalidArgument(String),
13 UnavailableOnThisMacOS(String),
15 TimedOut(String),
17 UnsupportedSourceLanguage(String),
19 UnsupportedTargetLanguage(String),
21 UnsupportedLanguagePairing(String),
23 UnableToIdentifyLanguage(String),
25 NothingToTranslate(String),
27 AlreadyCancelled(String),
29 NotInstalled(String),
31 Framework(String),
33 Unknown(String),
35}
36
37impl TranslationError {
38 #[must_use]
39 pub fn error_description(&self) -> &str {
41 split_payload(self.message()).0
42 }
43
44 #[must_use]
45 pub fn failure_reason(&self) -> Option<&str> {
47 split_payload(self.message()).1
48 }
49
50 fn message(&self) -> &str {
51 match self {
52 Self::InvalidArgument(message)
53 | Self::UnavailableOnThisMacOS(message)
54 | Self::TimedOut(message)
55 | Self::UnsupportedSourceLanguage(message)
56 | Self::UnsupportedTargetLanguage(message)
57 | Self::UnsupportedLanguagePairing(message)
58 | Self::UnableToIdentifyLanguage(message)
59 | Self::NothingToTranslate(message)
60 | Self::AlreadyCancelled(message)
61 | Self::NotInstalled(message)
62 | Self::Framework(message)
63 | Self::Unknown(message) => message,
64 }
65 }
66
67 pub(crate) fn from_status_parts(
68 status: i32,
69 description: String,
70 failure_reason: Option<String>,
71 ) -> Self {
72 let message = encode_payload(description, failure_reason);
73 match status {
74 ffi::status::INVALID_ARGUMENT => Self::InvalidArgument(message),
75 ffi::status::UNAVAILABLE_ON_THIS_MACOS => Self::UnavailableOnThisMacOS(message),
76 ffi::status::TIMED_OUT => Self::TimedOut(message),
77 ffi::status::UNSUPPORTED_SOURCE_LANGUAGE => Self::UnsupportedSourceLanguage(message),
78 ffi::status::UNSUPPORTED_TARGET_LANGUAGE => Self::UnsupportedTargetLanguage(message),
79 ffi::status::UNSUPPORTED_LANGUAGE_PAIRING => Self::UnsupportedLanguagePairing(message),
80 ffi::status::UNABLE_TO_IDENTIFY_LANGUAGE => Self::UnableToIdentifyLanguage(message),
81 ffi::status::NOTHING_TO_TRANSLATE => Self::NothingToTranslate(message),
82 ffi::status::ALREADY_CANCELLED => Self::AlreadyCancelled(message),
83 ffi::status::NOT_INSTALLED => Self::NotInstalled(message),
84 ffi::status::FRAMEWORK_ERROR => Self::Framework(message),
85 _ => Self::Unknown(message),
86 }
87 }
88}
89
90impl fmt::Display for TranslationError {
91 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92 match self.failure_reason() {
93 Some(failure_reason) => {
94 write!(f, "{}: {failure_reason}", self.error_description())
95 }
96 None => f.write_str(self.error_description()),
97 }
98 }
99}
100
101impl Error for TranslationError {}
102
103fn encode_payload(description: String, failure_reason: Option<String>) -> String {
104 match failure_reason {
105 Some(failure_reason) if !failure_reason.is_empty() => {
106 format!("{description}{FAILURE_REASON_DELIMITER}{failure_reason}")
107 }
108 _ => description,
109 }
110}
111
112fn split_payload(message: &str) -> (&str, Option<&str>) {
113 match message.split_once(FAILURE_REASON_DELIMITER) {
114 Some((description, failure_reason)) if !failure_reason.is_empty() => {
115 (description, Some(failure_reason))
116 }
117 _ => (message, None),
118 }
119}