From 4be6b8b0d7344a6b51936ca7438b19226b1e515d Mon Sep 17 00:00:00 2001 From: Ryo Yamashita Date: Thu, 28 Sep 2023 23:53:25 +0900 Subject: [PATCH 01/11] [skip ci] WIP --- crates/voicevox_core/src/error.rs | 12 +++--------- crates/voicevox_core/src/user_dict/word.rs | 9 ++++++--- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/crates/voicevox_core/src/error.rs b/crates/voicevox_core/src/error.rs index ce4a90b33..9674619bd 100644 --- a/crates/voicevox_core/src/error.rs +++ b/crates/voicevox_core/src/error.rs @@ -16,6 +16,7 @@ pub struct Error(#[from] ErrorRepr); [ LoadModelError ]; [ FullContextLabelError ]; [ KanaParseError ]; + [ InvalidWordError ]; )] impl From for Error { fn from(err: E) -> Self { @@ -23,13 +24,6 @@ impl From for Error { } } -// FIXME: `ErrorRepr::InvalidWord`を`#[error(transparent)]`にする -impl From for Error { - fn from(err: InvalidWordError) -> Self { - ErrorRepr::InvalidWord(err).into() - } -} - impl Error { /// 対応する[`ErrorKind`]を返す。 pub fn kind(&self) -> ErrorKind { @@ -105,8 +99,8 @@ pub(crate) enum ErrorRepr { #[error("OpenJTalkのユーザー辞書の設定に失敗しました: {0}")] UseUserDict(String), - #[error("ユーザー辞書の単語のバリデーションに失敗しました: {0}")] - InvalidWord(InvalidWordError), + #[error(transparent)] + InvalidWord(#[from] InvalidWordError), } /// エラーの種類。 diff --git a/crates/voicevox_core/src/user_dict/word.rs b/crates/voicevox_core/src/user_dict/word.rs index 6a43958db..0a737adbf 100644 --- a/crates/voicevox_core/src/user_dict/word.rs +++ b/crates/voicevox_core/src/user_dict/word.rs @@ -58,13 +58,16 @@ impl<'de> Deserialize<'de> for UserDictWord { #[allow(clippy::enum_variant_names)] // FIXME #[derive(thiserror::Error, Debug, PartialEq)] pub(crate) enum InvalidWordError { - #[error("無効な発音です({1}): {0:?}")] + #[error("{BASE_ERROR_MESSAGE}: 無効な発音です({1}): {0:?}")] InvalidPronunciation(String, &'static str), - #[error("優先度は{MIN_PRIORITY}以上{MAX_PRIORITY}以下である必要があります: {0}")] + #[error("{BASE_ERROR_MESSAGE}: 優先度は{MIN_PRIORITY}以上{MAX_PRIORITY}以下である必要があります: {0}")] InvalidPriority(u32), - #[error("誤ったアクセント型です({1:?}の範囲から外れています): {0}")] + #[error("{BASE_ERROR_MESSAGE}: 誤ったアクセント型です({1:?}の範囲から外れています): {0}")] InvalidAccentType(usize, RangeToInclusive), } + +const BASE_ERROR_MESSAGE: &str = "ユーザー辞書の単語のバリデーションに失敗しました"; + type InvalidWordResult = std::result::Result; static PRONUNCIATION_REGEX: Lazy = Lazy::new(|| Regex::new(r"^[ァ-ヴー]+$").unwrap()); From 9646634b6253967bb751aacc5208e33348779504 Mon Sep 17 00:00:00 2001 From: Ryo Yamashita Date: Fri, 29 Sep 2023 01:19:22 +0900 Subject: [PATCH 02/11] =?UTF-8?q?[skip=20ci]=20=E4=B8=8D=E8=A6=81=E3=81=AA?= =?UTF-8?q?`map=5Ferr`=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/voicevox_core/src/user_dict/word.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/voicevox_core/src/user_dict/word.rs b/crates/voicevox_core/src/user_dict/word.rs index 0a737adbf..4e316ad6d 100644 --- a/crates/voicevox_core/src/user_dict/word.rs +++ b/crates/voicevox_core/src/user_dict/word.rs @@ -108,9 +108,8 @@ impl UserDictWord { if MIN_PRIORITY > priority || priority > MAX_PRIORITY { return Err(ErrorRepr::InvalidWord(InvalidWordError::InvalidPriority(priority)).into()); } - validate_pronunciation(&pronunciation).map_err(ErrorRepr::InvalidWord)?; - let mora_count = - calculate_mora_count(&pronunciation, accent_type).map_err(ErrorRepr::InvalidWord)?; + validate_pronunciation(&pronunciation)?; + let mora_count = calculate_mora_count(&pronunciation, accent_type)?; Ok(Self { surface: to_zenkaku(surface), pronunciation, From 6ddda132472348d6d3639e7ad03cd0ce2335d31f Mon Sep 17 00:00:00 2001 From: Ryo Yamashita Date: Fri, 29 Sep 2023 01:35:18 +0900 Subject: [PATCH 03/11] =?UTF-8?q?[skip=20ci]=20=E5=AE=9A=E6=95=B0=E3=82=92?= =?UTF-8?q?=E9=96=A2=E9=80=A3=E5=AE=9A=E6=95=B0=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/voicevox_core/src/user_dict/word.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/crates/voicevox_core/src/user_dict/word.rs b/crates/voicevox_core/src/user_dict/word.rs index 4e316ad6d..dfa04b046 100644 --- a/crates/voicevox_core/src/user_dict/word.rs +++ b/crates/voicevox_core/src/user_dict/word.rs @@ -58,15 +58,23 @@ impl<'de> Deserialize<'de> for UserDictWord { #[allow(clippy::enum_variant_names)] // FIXME #[derive(thiserror::Error, Debug, PartialEq)] pub(crate) enum InvalidWordError { - #[error("{BASE_ERROR_MESSAGE}: 無効な発音です({1}): {0:?}")] + #[error("{}: 無効な発音です({_1}): {_0:?}", Self::BASE_MSG)] InvalidPronunciation(String, &'static str), - #[error("{BASE_ERROR_MESSAGE}: 優先度は{MIN_PRIORITY}以上{MAX_PRIORITY}以下である必要があります: {0}")] + #[error( + "{}: 優先度は{MIN_PRIORITY}以上{MAX_PRIORITY}以下である必要があります: {_0}", + Self::BASE_MSG + )] InvalidPriority(u32), - #[error("{BASE_ERROR_MESSAGE}: 誤ったアクセント型です({1:?}の範囲から外れています): {0}")] + #[error( + "{}: 誤ったアクセント型です({1:?}の範囲から外れています): {_0}", + Self::BASE_MSG + )] InvalidAccentType(usize, RangeToInclusive), } -const BASE_ERROR_MESSAGE: &str = "ユーザー辞書の単語のバリデーションに失敗しました"; +impl InvalidWordError { + const BASE_MSG: &str = "ユーザー辞書の単語のバリデーションに失敗しました"; +} type InvalidWordResult = std::result::Result; From b2dc84d175aa3e068f560421d92775e6e4f3adab Mon Sep 17 00:00:00 2001 From: Ryo Yamashita Date: Sun, 1 Oct 2023 18:26:07 +0900 Subject: [PATCH 04/11] `UseUserDict` --- crates/voicevox_core/src/engine/open_jtalk.rs | 13 ++++++------- crates/voicevox_core/src/error.rs | 4 ++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/crates/voicevox_core/src/engine/open_jtalk.rs b/crates/voicevox_core/src/engine/open_jtalk.rs index b67709b08..229ff7ccf 100644 --- a/crates/voicevox_core/src/engine/open_jtalk.rs +++ b/crates/voicevox_core/src/engine/open_jtalk.rs @@ -3,6 +3,8 @@ use std::{ path::{Path, PathBuf}, sync::Mutex, }; + +use anyhow::anyhow; use tempfile::NamedTempFile; use ::open_jtalk::*; @@ -70,13 +72,12 @@ impl OpenJtalk { .ok_or(ErrorRepr::NotLoadedOpenjtalkDict)?; // ユーザー辞書用のcsvを作成 - let mut temp_csv = - NamedTempFile::new().map_err(|e| ErrorRepr::UseUserDict(e.to_string()))?; + let mut temp_csv = NamedTempFile::new().map_err(|e| ErrorRepr::UseUserDict(e.into()))?; temp_csv .write_all(user_dict.to_mecab_format().as_bytes()) - .map_err(|e| ErrorRepr::UseUserDict(e.to_string()))?; + .map_err(|e| ErrorRepr::UseUserDict(e.into()))?; let temp_csv_path = temp_csv.into_temp_path(); - let temp_dict = NamedTempFile::new().map_err(|e| ErrorRepr::UseUserDict(e.to_string()))?; + let temp_dict = NamedTempFile::new().map_err(|e| ErrorRepr::UseUserDict(e.into()))?; let temp_dict_path = temp_dict.into_temp_path(); // Mecabでユーザー辞書をコンパイル @@ -100,9 +101,7 @@ impl OpenJtalk { let result = mecab.load_with_userdic(Path::new(dict_dir), Some(Path::new(&temp_dict_path))); if !result { - return Err( - ErrorRepr::UseUserDict("辞書のコンパイルに失敗しました".to_string()).into(), - ); + return Err(ErrorRepr::UseUserDict(anyhow!("辞書のコンパイルに失敗しました")).into()); } Ok(()) diff --git a/crates/voicevox_core/src/error.rs b/crates/voicevox_core/src/error.rs index 9674619bd..252eb321b 100644 --- a/crates/voicevox_core/src/error.rs +++ b/crates/voicevox_core/src/error.rs @@ -96,8 +96,8 @@ pub(crate) enum ErrorRepr { #[error("ユーザー辞書に単語が見つかりませんでした: {0}")] WordNotFound(Uuid), - #[error("OpenJTalkのユーザー辞書の設定に失敗しました: {0}")] - UseUserDict(String), + #[error("OpenJTalkのユーザー辞書の設定に失敗しました")] + UseUserDict(#[source] anyhow::Error), #[error(transparent)] InvalidWord(#[from] InvalidWordError), From 152bd1d168d4b7c21f514d8e10af0b613808afda Mon Sep 17 00:00:00 2001 From: Ryo Yamashita Date: Sun, 1 Oct 2023 18:28:00 +0900 Subject: [PATCH 05/11] `SaveUserDict` --- crates/voicevox_core/src/error.rs | 4 ++-- crates/voicevox_core/src/user_dict/dict.rs | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/voicevox_core/src/error.rs b/crates/voicevox_core/src/error.rs index 252eb321b..66244853a 100644 --- a/crates/voicevox_core/src/error.rs +++ b/crates/voicevox_core/src/error.rs @@ -90,8 +90,8 @@ pub(crate) enum ErrorRepr { #[error("ユーザー辞書を読み込めませんでした: {0}")] LoadUserDict(String), - #[error("ユーザー辞書を書き込めませんでした: {0}")] - SaveUserDict(String), + #[error("ユーザー辞書を書き込めませんでした")] + SaveUserDict(#[source] anyhow::Error), #[error("ユーザー辞書に単語が見つかりませんでした: {0}")] WordNotFound(Uuid), diff --git a/crates/voicevox_core/src/user_dict/dict.rs b/crates/voicevox_core/src/user_dict/dict.rs index dd342ddd0..8a384059a 100644 --- a/crates/voicevox_core/src/user_dict/dict.rs +++ b/crates/voicevox_core/src/user_dict/dict.rs @@ -72,10 +72,9 @@ impl UserDict { /// ユーザー辞書を保存する。 pub fn save(&self, store_path: &str) -> Result<()> { - let mut file = - File::create(store_path).map_err(|e| ErrorRepr::SaveUserDict(e.to_string()))?; + let mut file = File::create(store_path).map_err(|e| ErrorRepr::SaveUserDict(e.into()))?; serde_json::to_writer(&mut file, &self.words) - .map_err(|e| ErrorRepr::SaveUserDict(e.to_string()))?; + .map_err(|e| ErrorRepr::SaveUserDict(e.into()))?; Ok(()) } From d4a54f6bd4d730fc194d3d387f6d2b29a9a114b3 Mon Sep 17 00:00:00 2001 From: Ryo Yamashita Date: Sun, 1 Oct 2023 18:28:36 +0900 Subject: [PATCH 06/11] `LoadUserDict` --- crates/voicevox_core/src/error.rs | 4 ++-- crates/voicevox_core/src/user_dict/dict.rs | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/crates/voicevox_core/src/error.rs b/crates/voicevox_core/src/error.rs index 66244853a..191d664fb 100644 --- a/crates/voicevox_core/src/error.rs +++ b/crates/voicevox_core/src/error.rs @@ -87,8 +87,8 @@ pub(crate) enum ErrorRepr { #[error("入力テキストをAquesTalk風記法としてパースすることに失敗しました,{0}")] ParseKana(#[from] KanaParseError), - #[error("ユーザー辞書を読み込めませんでした: {0}")] - LoadUserDict(String), + #[error("ユーザー辞書を読み込めませんでした")] + LoadUserDict(#[source] anyhow::Error), #[error("ユーザー辞書を書き込めませんでした")] SaveUserDict(#[source] anyhow::Error), diff --git a/crates/voicevox_core/src/user_dict/dict.rs b/crates/voicevox_core/src/user_dict/dict.rs index 8a384059a..1a7820a78 100644 --- a/crates/voicevox_core/src/user_dict/dict.rs +++ b/crates/voicevox_core/src/user_dict/dict.rs @@ -28,11 +28,10 @@ impl UserDict { pub fn load(&mut self, store_path: &str) -> Result<()> { let store_path = std::path::Path::new(store_path); - let store_file = - File::open(store_path).map_err(|e| ErrorRepr::LoadUserDict(e.to_string()))?; + let store_file = File::open(store_path).map_err(|e| ErrorRepr::LoadUserDict(e.into()))?; - let words: IndexMap = serde_json::from_reader(store_file) - .map_err(|e| ErrorRepr::LoadUserDict(e.to_string()))?; + let words: IndexMap = + serde_json::from_reader(store_file).map_err(|e| ErrorRepr::LoadUserDict(e.into()))?; self.words.extend(words); Ok(()) From aee8edfb479c5869b76dcde1669f82e09af88d43 Mon Sep 17 00:00:00 2001 From: Ryo Yamashita Date: Sun, 1 Oct 2023 18:51:41 +0900 Subject: [PATCH 07/11] `ParseKana` --- crates/voicevox_core/src/engine/kana_parser.rs | 11 ++--------- crates/voicevox_core/src/error.rs | 2 +- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/crates/voicevox_core/src/engine/kana_parser.rs b/crates/voicevox_core/src/engine/kana_parser.rs index 14a3aa70d..5bd09f3e6 100644 --- a/crates/voicevox_core/src/engine/kana_parser.rs +++ b/crates/voicevox_core/src/engine/kana_parser.rs @@ -10,17 +10,10 @@ const PAUSE_DELIMITER: char = '、'; const WIDE_INTERROGATION_MARK: char = '?'; const LOOP_LIMIT: usize = 300; -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)] +#[error("入力テキストをAquesTalk風記法としてパースすることに失敗しました: {_0}")] pub(crate) struct KanaParseError(String); -impl std::fmt::Display for KanaParseError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "Parse Error: {}", self.0) - } -} - -impl std::error::Error for KanaParseError {} - type KanaParseResult = std::result::Result; static TEXT2MORA_WITH_UNVOICE: Lazy> = Lazy::new(|| { diff --git a/crates/voicevox_core/src/error.rs b/crates/voicevox_core/src/error.rs index 191d664fb..fa40d853d 100644 --- a/crates/voicevox_core/src/error.rs +++ b/crates/voicevox_core/src/error.rs @@ -84,7 +84,7 @@ pub(crate) enum ErrorRepr { #[error("入力テキストからのフルコンテキストラベル抽出に失敗しました,{0}")] ExtractFullContextLabel(#[from] FullContextLabelError), - #[error("入力テキストをAquesTalk風記法としてパースすることに失敗しました,{0}")] + #[error(transparent)] ParseKana(#[from] KanaParseError), #[error("ユーザー辞書を読み込めませんでした")] From ee8863e23daea8af73ecd11b452732abf40b57a3 Mon Sep 17 00:00:00 2001 From: Ryo Yamashita Date: Sun, 1 Oct 2023 20:32:43 +0900 Subject: [PATCH 08/11] `ExtractFullContextLabel` --- .../src/engine/full_context_label.rs | 66 +++++++++++------- crates/voicevox_core/src/engine/open_jtalk.rs | 69 +++++++++---------- crates/voicevox_core/src/error.rs | 2 +- 3 files changed, 77 insertions(+), 60 deletions(-) diff --git a/crates/voicevox_core/src/engine/full_context_label.rs b/crates/voicevox_core/src/engine/full_context_label.rs index 31471c004..667dbc8b1 100644 --- a/crates/voicevox_core/src/engine/full_context_label.rs +++ b/crates/voicevox_core/src/engine/full_context_label.rs @@ -1,22 +1,32 @@ use std::collections::HashMap; use super::*; +use crate::engine::open_jtalk::OpenjtalkFunctionError; use once_cell::sync::Lazy; use regex::Regex; +// FIXME: 入力テキストをここで持って、メッセージに含む #[derive(thiserror::Error, Debug)] -pub(crate) enum FullContextLabelError { - #[error("label parse error label:{label}")] +#[error("入力テキストからのフルコンテキストラベル抽出に失敗しました: {context}")] +pub(crate) struct FullContextLabelError { + context: ErrorKind, + #[source] + source: Option, +} + +#[derive(derive_more::Display, Debug)] +enum ErrorKind { + #[display(fmt = "Open JTalkで解釈することができませんでした")] + OpenJtalk, + + #[display(fmt = "label parse error label: {label}")] LabelParse { label: String }, - #[error("too long mora mora_phonemes:{mora_phonemes:?}")] + #[display(fmt = "too long mora mora_phonemes: {mora_phonemes:?}")] TooLongMora { mora_phonemes: Vec }, - #[error("invalid mora:{mora:?}")] + #[display(fmt = "invalid mora: {mora:?}")] InvalidMora { mora: Box }, - - #[error(transparent)] - OpenJtalk(#[from] open_jtalk::OpenJtalkError), } type Result = std::result::Result; @@ -38,18 +48,18 @@ static H1_REGEX: Lazy = Lazy::new(|| Regex::new(r"(/H:(\d+|xx)_)").unwrap static I3_REGEX: Lazy = Lazy::new(|| Regex::new(r"(@(\d+|xx)\+)").unwrap()); static J1_REGEX: Lazy = Lazy::new(|| Regex::new(r"(/J:(\d+|xx)_)").unwrap()); -fn string_feature_by_regex(re: &Regex, label: &str) -> Result { +fn string_feature_by_regex(re: &Regex, label: &str) -> std::result::Result { if let Some(caps) = re.captures(label) { Ok(caps.get(2).unwrap().as_str().to_string()) } else { - Err(FullContextLabelError::LabelParse { + Err(ErrorKind::LabelParse { label: label.into(), }) } } impl Phoneme { - pub(crate) fn from_label(label: impl Into) -> Result { + fn from_label(label: impl Into) -> std::result::Result { let mut contexts = HashMap::::with_capacity(10); let label = label.into(); contexts.insert("p3".into(), string_feature_by_regex(&P3_REGEX, &label)?); @@ -116,7 +126,7 @@ pub struct AccentPhrase { } impl AccentPhrase { - pub(crate) fn from_phonemes(mut phonemes: Vec) -> Result { + fn from_phonemes(mut phonemes: Vec) -> std::result::Result { let mut moras = Vec::with_capacity(phonemes.len()); let mut mora_phonemes = Vec::with_capacity(phonemes.len()); for i in 0..phonemes.len() { @@ -140,7 +150,7 @@ impl AccentPhrase { mora_phonemes.get(1).unwrap().clone(), )); } else { - return Err(FullContextLabelError::TooLongMora { mora_phonemes }); + return Err(ErrorKind::TooLongMora { mora_phonemes }); } mora_phonemes.clear(); } @@ -151,11 +161,11 @@ impl AccentPhrase { .vowel() .contexts() .get("f2") - .ok_or_else(|| FullContextLabelError::InvalidMora { + .ok_or_else(|| ErrorKind::InvalidMora { mora: mora.clone().into(), })? .parse() - .map_err(|_| FullContextLabelError::InvalidMora { + .map_err(|_| ErrorKind::InvalidMora { mora: mora.clone().into(), })?; @@ -208,7 +218,7 @@ pub struct BreathGroup { } impl BreathGroup { - pub(crate) fn from_phonemes(phonemes: Vec) -> Result { + fn from_phonemes(phonemes: Vec) -> std::result::Result { let mut accent_phrases = Vec::with_capacity(phonemes.len()); let mut accent_phonemes = Vec::with_capacity(phonemes.len()); for i in 0..phonemes.len() { @@ -256,7 +266,7 @@ pub struct Utterance { } impl Utterance { - pub(crate) fn from_phonemes(phonemes: Vec) -> Result { + fn from_phonemes(phonemes: Vec) -> std::result::Result { let mut breath_groups = vec![]; let mut group_phonemes = Vec::with_capacity(phonemes.len()); let mut pauses = vec![]; @@ -309,12 +319,22 @@ impl Utterance { open_jtalk: &open_jtalk::OpenJtalk, text: impl AsRef, ) -> Result { - let labels = open_jtalk.extract_fullcontext(text)?; - Self::from_phonemes( - labels - .into_iter() - .map(Phoneme::from_label) - .collect::>>()?, - ) + let labels = + open_jtalk + .extract_fullcontext(text) + .map_err(|source| FullContextLabelError { + context: ErrorKind::OpenJtalk, + source: Some(source), + })?; + + labels + .into_iter() + .map(Phoneme::from_label) + .collect::, _>>() + .and_then(Self::from_phonemes) + .map_err(|context| FullContextLabelError { + context, + source: None, + }) } } diff --git a/crates/voicevox_core/src/engine/open_jtalk.rs b/crates/voicevox_core/src/engine/open_jtalk.rs index 229ff7ccf..3c82859d8 100644 --- a/crates/voicevox_core/src/engine/open_jtalk.rs +++ b/crates/voicevox_core/src/engine/open_jtalk.rs @@ -12,19 +12,13 @@ use ::open_jtalk::*; use crate::{error::ErrorRepr, UserDict}; #[derive(thiserror::Error, Debug)] -pub(crate) enum OpenJtalkError { - #[error("open_jtalk load error")] - Load { mecab_dict_dir: PathBuf }, - #[error("open_jtalk extract_fullcontext error")] - ExtractFullContext { - text: String, - #[source] - source: Option, - }, +#[error("`{name}`の実行が失敗しました")] +pub(crate) struct OpenjtalkFunctionError { + name: &'static str, + #[source] + source: Option, } -type Result = std::result::Result; - /// テキスト解析器としてのOpen JTalk。 pub struct OpenJtalk { resources: Mutex, @@ -55,8 +49,10 @@ impl OpenJtalk { open_jtalk_dict_dir: impl AsRef, ) -> crate::result::Result { let mut s = Self::new_without_dic(); - s.load(open_jtalk_dict_dir) - .map_err(|_| ErrorRepr::NotLoadedOpenjtalkDict)?; + s.load(open_jtalk_dict_dir).map_err(|()| { + // FIXME: 「システム辞書を読もうとしたけど読めなかった」というエラーをちゃんと用意する + ErrorRepr::NotLoadedOpenjtalkDict + })?; Ok(s) } @@ -107,7 +103,10 @@ impl OpenJtalk { Ok(()) } - pub(crate) fn extract_fullcontext(&self, text: impl AsRef) -> Result> { + pub(crate) fn extract_fullcontext( + &self, + text: impl AsRef, + ) -> std::result::Result, OpenjtalkFunctionError> { let Resources { mecab, njd, @@ -118,19 +117,16 @@ impl OpenJtalk { njd.refresh(); mecab.refresh(); - let mecab_text = - text2mecab(text.as_ref()).map_err(|e| OpenJtalkError::ExtractFullContext { - text: text.as_ref().into(), - source: Some(e.into()), - })?; + let mecab_text = text2mecab(text.as_ref()).map_err(|e| OpenjtalkFunctionError { + name: "text2mecab", + source: Some(e), + })?; if mecab.analysis(mecab_text) { njd.mecab2njd( - mecab - .get_feature() - .ok_or(OpenJtalkError::ExtractFullContext { - text: text.as_ref().into(), - source: None, - })?, + mecab.get_feature().ok_or(OpenjtalkFunctionError { + name: "Mecab_get_feature", + source: None, + })?, mecab.get_size(), ); njd.set_pronunciation(); @@ -143,20 +139,20 @@ impl OpenJtalk { jpcommon.make_label(); jpcommon .get_label_feature_to_iter() - .ok_or_else(|| OpenJtalkError::ExtractFullContext { - text: text.as_ref().into(), + .ok_or(OpenjtalkFunctionError { + name: "JPCommon_get_label_feature", source: None, }) .map(|iter| iter.map(|s| s.to_string()).collect()) } else { - Err(OpenJtalkError::ExtractFullContext { - text: text.as_ref().into(), + Err(OpenjtalkFunctionError { + name: "Mecab_analysis", source: None, }) } } - fn load(&mut self, open_jtalk_dict_dir: impl AsRef) -> Result<()> { + fn load(&mut self, open_jtalk_dict_dir: impl AsRef) -> std::result::Result<(), ()> { let result = self .resources .lock() @@ -168,9 +164,7 @@ impl OpenJtalk { Ok(()) } else { self.dict_dir = None; - Err(OpenJtalkError::Load { - mecab_dict_dir: open_jtalk_dict_dir.as_ref().into(), - }) + Err(()) } } @@ -274,9 +268,12 @@ mod tests { } #[rstest] - #[case("",Err(OpenJtalkError::ExtractFullContext{text:"".into(),source:None}))] + #[case("", Err(OpenjtalkFunctionError { name: "Mecab_get_feature", source: None }))] #[case("こんにちは、ヒホです。", Ok(testdata_hello_hiho()))] - fn extract_fullcontext_works(#[case] text: &str, #[case] expected: super::Result>) { + fn extract_fullcontext_works( + #[case] text: &str, + #[case] expected: std::result::Result, OpenjtalkFunctionError>, + ) { let open_jtalk = OpenJtalk::new_with_initialize(OPEN_JTALK_DIC_DIR).unwrap(); let result = open_jtalk.extract_fullcontext(text); assert_debug_fmt_eq!(expected, result); @@ -286,7 +283,7 @@ mod tests { #[case("こんにちは、ヒホです。", Ok(testdata_hello_hiho()))] fn extract_fullcontext_loop_works( #[case] text: &str, - #[case] expected: super::Result>, + #[case] expected: std::result::Result, OpenjtalkFunctionError>, ) { let open_jtalk = OpenJtalk::new_with_initialize(OPEN_JTALK_DIC_DIR).unwrap(); for _ in 0..10 { diff --git a/crates/voicevox_core/src/error.rs b/crates/voicevox_core/src/error.rs index fa40d853d..231c6bbb3 100644 --- a/crates/voicevox_core/src/error.rs +++ b/crates/voicevox_core/src/error.rs @@ -81,7 +81,7 @@ pub(crate) enum ErrorRepr { #[error("推論に失敗しました")] InferenceFailed, - #[error("入力テキストからのフルコンテキストラベル抽出に失敗しました,{0}")] + #[error(transparent)] ExtractFullContextLabel(#[from] FullContextLabelError), #[error(transparent)] From a0cde52058a24e95cc40518c0386f185e1caff1b Mon Sep 17 00:00:00 2001 From: Ryo Yamashita Date: Sun, 1 Oct 2023 20:34:40 +0900 Subject: [PATCH 09/11] `GetSupportedDevices` --- crates/voicevox_core/src/devices.rs | 2 +- crates/voicevox_core/src/error.rs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/voicevox_core/src/devices.rs b/crates/voicevox_core/src/devices.rs index 673144881..70847cb81 100644 --- a/crates/voicevox_core/src/devices.rs +++ b/crates/voicevox_core/src/devices.rs @@ -45,7 +45,7 @@ impl SupportedDevices { let mut cuda_support = false; let mut dml_support = false; for provider in onnxruntime::session::get_available_providers() - .map_err(|e| ErrorRepr::GetSupportedDevices(e.into()))? + .map_err(ErrorRepr::GetSupportedDevices)? .iter() { match provider.as_str() { diff --git a/crates/voicevox_core/src/error.rs b/crates/voicevox_core/src/error.rs index 231c6bbb3..a85928c5d 100644 --- a/crates/voicevox_core/src/error.rs +++ b/crates/voicevox_core/src/error.rs @@ -2,6 +2,7 @@ use self::engine::{FullContextLabelError, KanaParseError}; use super::*; //use engine:: use duplicate::duplicate_item; +use onnxruntime::OrtError; use std::path::PathBuf; use thiserror::Error; use uuid::Uuid; @@ -63,8 +64,8 @@ pub(crate) enum ErrorRepr { #[error(transparent)] LoadModel(#[from] LoadModelError), - #[error("サポートされているデバイス情報取得中にエラーが発生しました,{0}")] - GetSupportedDevices(#[source] anyhow::Error), + #[error("サポートされているデバイス情報取得中にエラーが発生しました")] + GetSupportedDevices(#[source] OrtError), #[error( "`{style_id}`に対するスタイルが見つかりませんでした。音声モデルが読み込まれていないか、読\ From f3c203d7b1a7a579fcba77a1d94cfc75f2c81ca6 Mon Sep 17 00:00:00 2001 From: Ryo Yamashita Date: Sun, 1 Oct 2023 20:35:33 +0900 Subject: [PATCH 10/11] `LoadModel` --- crates/voicevox_core/src/error.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/voicevox_core/src/error.rs b/crates/voicevox_core/src/error.rs index a85928c5d..551bd8c52 100644 --- a/crates/voicevox_core/src/error.rs +++ b/crates/voicevox_core/src/error.rs @@ -149,10 +149,7 @@ pub(crate) type LoadModelResult = std::result::Result; /// 音声モデル読み込みのエラー。 #[derive(Error, Debug)] -#[error( - "`{path}`の読み込みに失敗しました: {context}{}", - source.as_ref().map(|e| format!(": {e}")).unwrap_or_default()) -] +#[error("`{path}`の読み込みに失敗しました: {context}")] pub(crate) struct LoadModelError { pub(crate) path: PathBuf, pub(crate) context: LoadModelErrorKind, From 11533110748e34343663ab6102528ad9e8fd17af Mon Sep 17 00:00:00 2001 From: Ryo Yamashita Date: Wed, 4 Oct 2023 04:11:06 +0900 Subject: [PATCH 11/11] =?UTF-8?q?`name`=20=E2=86=92=20`function`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/voicevox_core/src/engine/open_jtalk.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/voicevox_core/src/engine/open_jtalk.rs b/crates/voicevox_core/src/engine/open_jtalk.rs index 3c82859d8..f34b43751 100644 --- a/crates/voicevox_core/src/engine/open_jtalk.rs +++ b/crates/voicevox_core/src/engine/open_jtalk.rs @@ -12,9 +12,9 @@ use ::open_jtalk::*; use crate::{error::ErrorRepr, UserDict}; #[derive(thiserror::Error, Debug)] -#[error("`{name}`の実行が失敗しました")] +#[error("`{function}`の実行が失敗しました")] pub(crate) struct OpenjtalkFunctionError { - name: &'static str, + function: &'static str, #[source] source: Option, } @@ -118,13 +118,13 @@ impl OpenJtalk { mecab.refresh(); let mecab_text = text2mecab(text.as_ref()).map_err(|e| OpenjtalkFunctionError { - name: "text2mecab", + function: "text2mecab", source: Some(e), })?; if mecab.analysis(mecab_text) { njd.mecab2njd( mecab.get_feature().ok_or(OpenjtalkFunctionError { - name: "Mecab_get_feature", + function: "Mecab_get_feature", source: None, })?, mecab.get_size(), @@ -140,13 +140,13 @@ impl OpenJtalk { jpcommon .get_label_feature_to_iter() .ok_or(OpenjtalkFunctionError { - name: "JPCommon_get_label_feature", + function: "JPCommon_get_label_feature", source: None, }) .map(|iter| iter.map(|s| s.to_string()).collect()) } else { Err(OpenjtalkFunctionError { - name: "Mecab_analysis", + function: "Mecab_analysis", source: None, }) } @@ -268,7 +268,7 @@ mod tests { } #[rstest] - #[case("", Err(OpenjtalkFunctionError { name: "Mecab_get_feature", source: None }))] + #[case("", Err(OpenjtalkFunctionError { function: "Mecab_get_feature", source: None }))] #[case("こんにちは、ヒホです。", Ok(testdata_hello_hiho()))] fn extract_fullcontext_works( #[case] text: &str,