mod r_ref;
pub mod traits;
pub use r_ref::ReadingRef;
use self::traits::AsReadingRef;
#[cfg(feature = "furigana")]
use crate::furi::segment::kanji::as_kanji::AsKanjiSegment;
#[cfg(feature = "furigana")]
use crate::furi::{parse::reading::FuriToReadingParser, Furigana};
#[cfg(feature = "furigana")]
use crate::furi::{segment::AsSegment, segment::Segment, seq::FuriSequence};
#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[cfg_attr(feature = "with_serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Reading {
kana: String,
kanji: Option<String>,
}
impl Reading {
#[inline]
pub fn new(kana: String) -> Self {
Self { kana, kanji: None }
}
#[inline]
pub fn new_with_kanji(kana: String, kanji: String) -> Self {
Self {
kana,
kanji: Some(kanji),
}
}
#[inline]
pub fn new_raw(kana: String, kanji: Option<String>) -> Self {
Self { kana, kanji }
}
#[inline]
pub fn has_kanji(&self) -> bool {
self.kanji.is_some()
}
#[inline]
pub fn kanji_or_kana(&self) -> &str {
self.kanji.as_deref().unwrap_or(&self.kana)
}
#[inline]
pub fn kanji(&self) -> Option<&str> {
self.kanji.as_deref()
}
#[inline]
pub fn kana(&self) -> &str {
&self.kana
}
#[inline]
pub fn into_inner(self) -> (String, Option<String>) {
(self.kana, self.kanji)
}
}
impl AsReadingRef for Reading {
#[inline]
fn as_reading_ref(&self) -> ReadingRef {
ReadingRef::new_raw(&self.kana, self.kanji.as_deref())
}
}
impl PartialEq<ReadingRef<'_>> for Reading {
#[inline]
fn eq(&self, other: &ReadingRef) -> bool {
self.kana.as_str() == other.kana() && self.kanji.as_deref() == other.kanji()
}
}
#[cfg(feature = "furigana")]
impl From<&FuriSequence<Segment>> for Reading {
#[inline]
fn from(value: &FuriSequence<Segment>) -> Self {
let kana = value.kana_reading().to_string();
let kanji = value.has_kanji().then(|| value.kanji_reading().to_string());
Self { kana, kanji }
}
}
#[cfg(feature = "furigana")]
impl<T: AsRef<str>> From<&Furigana<T>> for Reading {
#[inline]
fn from(value: &Furigana<T>) -> Self {
let (kana, kanji) = FuriToReadingParser::parse_kanji_and_kana(value.raw());
Self::new_raw(kana, kanji)
}
}
#[cfg(feature = "furigana")]
impl<T: AsRef<str>> From<Furigana<T>> for Reading {
#[inline]
fn from(value: Furigana<T>) -> Self {
let (kana, kanji) = FuriToReadingParser::parse_kanji_and_kana(value.raw());
Self::new_raw(kana, kanji)
}
}
#[cfg(feature = "furigana")]
impl From<FuriSequence<Segment>> for Reading {
#[inline]
fn from(value: FuriSequence<Segment>) -> Self {
let kana = value.kana_reading().to_string();
let kanji = value.has_kanji().then(|| value.kanji_reading().to_string());
Self { kana, kanji }
}
}
#[cfg(feature = "furigana")]
impl<S: AsSegment> FromIterator<S> for Reading {
fn from_iter<T: IntoIterator<Item = S>>(iter: T) -> Reading {
let mut kana = String::with_capacity(20);
let mut kanji = String::new();
let mut has_kanji = false;
for i in iter {
if let Some(k) = i.as_kanji() {
if !has_kanji {
kanji = kana.clone();
has_kanji = true;
}
let readings = k.readings();
if readings.is_empty() || readings[0].as_ref().is_empty() {
kana.push_str(k.literals().as_ref());
kanji.push_str(k.literals().as_ref());
continue;
}
kanji.push_str(k.literals().as_ref());
for r in readings {
kana.push_str(r.as_ref());
}
} else if let Some(k) = i.as_kana() {
let k = k.as_ref();
kana.push_str(k);
if has_kanji {
kanji.push_str(k);
}
}
}
let kanji = has_kanji.then_some(kanji);
Reading::new_raw(kana, kanji)
}
}
#[cfg(feature = "furigana")]
impl<A> From<A> for Reading
where
A: AsSegment,
{
#[inline]
fn from(value: A) -> Self {
let kana = value.get_kana_reading();
let kanji = value.as_kanji().map(|i| i.literals().as_ref().to_string());
Self { kana, kanji }
}
}