From 39875af636a39a7e9172c1e9a16ad49b43ff178f Mon Sep 17 00:00:00 2001 From: Kan-Ru Chen Date: Mon, 15 Jul 2024 20:36:45 +0900 Subject: [PATCH] docs: Add docs for some modules --- src/conversion/chewing.rs | 6 ++--- src/conversion/fuzzy.rs | 3 ++- src/conversion/mod.rs | 31 +++++++++++++++-------- src/dictionary/loader.rs | 15 +++++++++++ src/dictionary/mod.rs | 2 +- src/dictionary/trie_buf.rs | 3 +++ src/editor/estimate.rs | 18 +++++++++----- src/zhuyin/syllable.rs | 51 +++++++++++++++++++++----------------- 8 files changed, 84 insertions(+), 45 deletions(-) diff --git a/src/conversion/chewing.rs b/src/conversion/chewing.rs index 85754fc2e..74649d7b6 100644 --- a/src/conversion/chewing.rs +++ b/src/conversion/chewing.rs @@ -11,7 +11,7 @@ use crate::dictionary::{Dictionary, LookupStrategy, Phrase}; use super::{Composition, ConversionEngine, Gap, Interval, Symbol}; -/// TODO: doc +/// The default Chewing conversion method. #[derive(Debug, Default)] pub struct ChewingEngine { pub(crate) lookup_strategy: LookupStrategy, @@ -19,13 +19,13 @@ pub struct ChewingEngine { impl ChewingEngine { const MAX_OUT_PATHS: usize = 100; - /// TODO: doc + /// Creates a new conversion engine. pub fn new() -> ChewingEngine { ChewingEngine { lookup_strategy: LookupStrategy::Standard, } } - pub fn convert<'a>( + pub(crate) fn convert<'a>( &'a self, dict: &'a dyn Dictionary, comp: &'a Composition, diff --git a/src/conversion/fuzzy.rs b/src/conversion/fuzzy.rs index ef1997481..34060c36c 100644 --- a/src/conversion/fuzzy.rs +++ b/src/conversion/fuzzy.rs @@ -2,13 +2,14 @@ use crate::dictionary::LookupStrategy; use super::{ChewingEngine, ConversionEngine}; -/// TODO: doc +/// Same conversion method as Chewing but uses fuzzy phrase search. #[derive(Debug, Default)] pub struct FuzzyChewingEngine { inner: ChewingEngine, } impl FuzzyChewingEngine { + /// Creates a new conversion engine. pub fn new() -> FuzzyChewingEngine { FuzzyChewingEngine { inner: ChewingEngine { diff --git a/src/conversion/mod.rs b/src/conversion/mod.rs index 121f08525..43fb6dd3b 100644 --- a/src/conversion/mod.rs +++ b/src/conversion/mod.rs @@ -21,6 +21,11 @@ pub use self::fuzzy::FuzzyChewingEngine; pub use self::simple::SimpleEngine; pub(crate) use self::symbol::{full_width_symbol_input, special_symbol_input}; +/// Converts a composition buffer to list of intervals. +/// +/// [`Composition`] contains all user inputs and selection information. The out +/// put intervals should cover the whole range of inputs, sorted in first in +/// first out order. pub trait ConversionEngine: Debug { fn convert<'a>( &'a self, @@ -29,16 +34,18 @@ pub trait ConversionEngine: Debug { ) -> Box> + 'a>; } -/// TODO: doc +/// Output of conversion. +/// +/// Interval represents a segment of input buffer converted to a phrase. #[derive(Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)] pub struct Interval { - /// TODO: doc + /// The starting offset of the interval. pub start: usize, - /// TODO: doc + /// The end (exclusive) of the interval. pub end: usize, - // TODO doc + /// Whether the output is a phrase from dictionary or just symbols. pub is_phrase: bool, - /// TODO: doc + /// The output string. pub str: Box, } @@ -52,7 +59,7 @@ impl Debug for Interval { } impl Interval { - /// TODO: doc + /// Whether the interval covers the whole range of the other interval. pub fn contains(&self, other: &Interval) -> bool { self.contains_range(other.start, other.end) } @@ -62,17 +69,18 @@ impl Interval { fn is_contained_by(&self, start: usize, end: usize) -> bool { start <= self.start && end >= self.end } + /// Whether the interval covers the part of the other interval. pub fn intersect(&self, other: &Interval) -> bool { self.intersect_range(other.start, other.end) } fn intersect_range(&self, start: usize, end: usize) -> bool { max(self.start, start) < min(self.end, end) } - /// TODO: doc + /// The length of the interval. pub fn len(&self) -> usize { self.end - self.start } - /// TODO: doc + /// Whether the interval is empty (no output). pub fn is_empty(&self) -> bool { self.len() == 0 } @@ -166,13 +174,14 @@ impl SyllableSlice for Vec { } } -/// TODO: doc +/// Input data collected by the Editor. #[derive(Debug, Default, Clone)] pub struct Composition { - /// TODO: doc + /// Pre-edit inputs either syllables or symbols. symbols: Vec, + /// User indicates offset that shouldn't form a phrase. gaps: Vec, - /// TODO: doc + /// User set constraint on that output must match. selections: Vec, } diff --git a/src/dictionary/loader.rs b/src/dictionary/loader.rs index 205b428f1..2de0a7cfa 100644 --- a/src/dictionary/loader.rs +++ b/src/dictionary/loader.rs @@ -27,6 +27,7 @@ const UD_MEM_FILE_NAME: &str = ":memory:"; const ABBREV_FILE_NAME: &str = "swkb.dat"; const SYMBOLS_FILE_NAME: &str = "symbols.dat"; +/// Automatically searchs and loads system dictionaries. #[derive(Debug, Default)] pub struct SystemDictionaryLoader { sys_path: Option, @@ -54,13 +55,18 @@ fn io_err(err: io::Error) -> LoadDictionaryError { } impl SystemDictionaryLoader { + /// Creates a new system dictionary loader. pub fn new() -> SystemDictionaryLoader { SystemDictionaryLoader::default() } + /// Override the default system dictionary search path. pub fn sys_path(mut self, path: impl Into) -> SystemDictionaryLoader { self.sys_path = Some(path.into()); self } + /// Searches and loads the system dictionaries and extra dictionaries. + /// + /// If no dictionary were found, a builtn minimum dictionary will be loaded. pub fn load(&self) -> Result>, LoadDictionaryError> { let search_path = if let Some(sys_path) = &self.sys_path { sys_path.to_owned() @@ -93,6 +99,7 @@ impl SystemDictionaryLoader { Ok(results) } + /// Loads the abbrev table. pub fn load_abbrev(&self) -> Result { let search_path = if let Some(sys_path) = &self.sys_path { sys_path.to_owned() @@ -105,6 +112,7 @@ impl SystemDictionaryLoader { info!("Loading {ABBREV_FILE_NAME}"); AbbrevTable::open(abbrev_path).map_err(io_err) } + /// Loads the symbol table. pub fn load_symbol_selector(&self) -> Result { let search_path = if let Some(sys_path) = &self.sys_path { sys_path.to_owned() @@ -119,19 +127,26 @@ impl SystemDictionaryLoader { } } +/// Automatically searches and loads the user dictionary. #[derive(Debug, Default)] pub struct UserDictionaryLoader { data_path: Option, } impl UserDictionaryLoader { + /// Creates a user dictionary loader. pub fn new() -> UserDictionaryLoader { UserDictionaryLoader::default() } + /// Override the default user dictionary search path. pub fn userphrase_path(mut self, path: impl AsRef) -> UserDictionaryLoader { self.data_path = Some(path.as_ref().to_path_buf()); self } + /// Searches and loads the user dictionary. + /// + /// If no user dictionary were found, a new dictionary will be created at + /// the default path. pub fn load(self) -> io::Result> { let data_path = self .data_path diff --git a/src/dictionary/mod.rs b/src/dictionary/mod.rs index 8b0ba77a5..6a352f73e 100644 --- a/src/dictionary/mod.rs +++ b/src/dictionary/mod.rs @@ -428,7 +428,7 @@ pub trait DictionaryMut: Debug { ) -> Result<(), UpdateDictionaryError>; } -/// TODO: doc +/// Errors during dictionary construction. #[derive(Debug)] pub struct BuildDictionaryError { source: Box, diff --git a/src/dictionary/trie_buf.rs b/src/dictionary/trie_buf.rs index b043c4ff2..978944d1a 100644 --- a/src/dictionary/trie_buf.rs +++ b/src/dictionary/trie_buf.rs @@ -16,6 +16,7 @@ use super::{ LookupStrategy, Phrase, Trie, TrieBuilder, UpdateDictionaryError, }; +/// A mutable dictionary backed by a Trie and a BTreeMap. #[derive(Debug)] pub struct TrieBuf { trie: Option, @@ -35,6 +36,7 @@ fn software_version() -> String { } impl TrieBuf { + /// Open the target Trie dictionary and wrap it create a TrieBuf. pub fn open>(path: P) -> io::Result { let path = path.into(); if !path.exists() { @@ -63,6 +65,7 @@ impl TrieBuf { }) } + /// Creates a pure in memory dictionary. pub fn new_in_memory() -> TrieBuf { TrieBuf { trie: None, diff --git a/src/editor/estimate.rs b/src/editor/estimate.rs index 14c3bf0ce..90bfed425 100644 --- a/src/editor/estimate.rs +++ b/src/editor/estimate.rs @@ -1,23 +1,28 @@ use crate::dictionary::{Dictionary, Phrase}; -/// TODO: doc +/// Estimates new user phrase frequency. +/// +/// Use UserFreqEstimate to keep track of the time passed and use the original +/// frequency and time to calculate the new frequency of user phrases. pub trait UserFreqEstimate { - /// TODO: doc + /// Increments the time passed. + /// + /// This should be called for every user interaction. fn tick(&mut self); - /// TODO: doc + /// Returns the current time in ticks. fn now(&self) -> u64; - /// TODO: doc + /// Returns the estimated new user phrase frequency. fn estimate(&self, phrase: &Phrase, orig_freq: u32, max_freq: u32) -> u32; } -/// TODO: doc +/// Loosely tracks time without persisting to disk. #[derive(Debug)] pub struct LaxUserFreqEstimate { lifetime: u64, } impl LaxUserFreqEstimate { - /// TODO: doc + /// Initialize with the last time value from the user dictionary. pub fn max_from(user_dict: &dyn Dictionary) -> LaxUserFreqEstimate { let lifetime = user_dict .entries() @@ -27,6 +32,7 @@ impl LaxUserFreqEstimate { LaxUserFreqEstimate { lifetime } } + /// Creates a new LaxUserFreqEstimate from a initial epoch. pub fn new(initial_lifetime: u64) -> LaxUserFreqEstimate { LaxUserFreqEstimate { lifetime: initial_lifetime, diff --git a/src/zhuyin/syllable.rs b/src/zhuyin/syllable.rs index ef1c7930f..aa0b87894 100644 --- a/src/zhuyin/syllable.rs +++ b/src/zhuyin/syllable.rs @@ -36,15 +36,15 @@ impl Syllable { None => unreachable!(), }, }; - /// TODO: docs + /// Creates a new empty syllable. pub const fn new() -> Syllable { Syllable::EMPTY } - /// TODO: docs + /// Creates a new syllable builder. pub const fn builder() -> SyllableBuilder { SyllableBuilder::new() } - /// TODO: docs + /// Returns the initial part of the syllable. pub const fn initial(&self) -> Option { let index = (self.value.get() & 0b0111111_00_0000_000) >> 9; if index == 0 { @@ -53,7 +53,7 @@ impl Syllable { Bopomofo::from_initial(index - 1) } } - /// TODO: docs + /// Returns the medial part of the syllable. pub const fn medial(&self) -> Option { let index = (self.value.get() & 0b0000000_11_0000_000) >> 7; if index == 0 { @@ -62,7 +62,7 @@ impl Syllable { Bopomofo::from_medial(index - 1) } } - /// TODO: docs + /// Returns the rime part of the syllable. pub const fn rime(&self) -> Option { let index = (self.value.get() & 0b0000000_00_1111_000) >> 3; if index == 0 { @@ -71,7 +71,7 @@ impl Syllable { Bopomofo::from_rime(index - 1) } } - /// TODO: docs + /// Returns the tone of the syllable. pub const fn tone(&self) -> Option { let index = self.value.get() & 0b0000000_00_0000_111; if index == 0 { @@ -80,7 +80,7 @@ impl Syllable { Bopomofo::from_tone(index - 1) } } - /// TODO: docs + /// Removes the initial from the syllable. pub fn remove_initial(&mut self) -> Option { let ret = self.initial(); let value = self.value.get() & 0b0000000_11_1111_111; @@ -90,7 +90,7 @@ impl Syllable { }; ret } - /// TODO: docs + /// Removes the medial from the syllable. pub fn remove_medial(&mut self) -> Option { let ret = self.medial(); let value = self.value.get() & 0b1111111_00_1111_111; @@ -100,7 +100,7 @@ impl Syllable { }; ret } - /// TODO: docs + /// Removes the rime from the syllable. pub fn remove_rime(&mut self) -> Option { let ret = self.rime(); let value = self.value.get() & 0b1111111_11_0000_111; @@ -110,7 +110,7 @@ impl Syllable { }; ret } - /// TODO: docs + /// Removes the tone from the syllable. pub fn remove_tone(&mut self) -> Option { let ret = self.tone(); let value = self.value.get() & 0b1111111_11_1111_000; @@ -120,26 +120,27 @@ impl Syllable { }; ret } - /// TODO: docs + /// Returns whether the syllable is empty. pub const fn is_empty(&self) -> bool { self.value.get() == Syllable::EMPTY.value.get() } - /// TODO: docs + /// Returns whether the syllable has an initial. pub fn has_initial(&self) -> bool { self.initial().is_some() } - /// TODO: docs + /// Returns whether the syllable has a medial pub fn has_medial(&self) -> bool { self.medial().is_some() } - /// TODO: docs + /// Returns whether the syllable has a rime. pub fn has_rime(&self) -> bool { self.rime().is_some() } - /// TODO: docs + /// Returns whether the syllable has a tone. pub fn has_tone(&self) -> bool { self.tone().is_some() } + /// Returns whether the syllable partially matches another syllable. pub fn starts_with(&self, other: Syllable) -> bool { let trailing_zeros = other.to_u16().trailing_zeros(); let mask = if trailing_zeros >= 9 { @@ -183,7 +184,7 @@ impl Syllable { fn to_le_bytes(self) -> [u8; 2] { self.to_u16().to_le_bytes() } - /// TODO: docs + /// Combines the current syllable with a new sound. pub fn update(&mut self, bopomofo: Bopomofo) { let orig = self.value.get(); let value = match bopomofo.kind() { @@ -194,7 +195,7 @@ impl Syllable { }; self.value = NonZeroU16::new(value).unwrap(); } - /// TODO: docs + /// Removes components of the syllable. pub fn pop(&mut self) -> Option { if self.has_tone() { return self.remove_tone(); @@ -210,7 +211,7 @@ impl Syllable { } None } - /// TODO: docs + /// Resets the syllable to empty. pub fn clear(&mut self) { *self = Syllable::EMPTY } @@ -264,6 +265,7 @@ impl AsRef for Syllable { } } +/// A slice that can be converted to a slice of syllables. pub trait SyllableSlice: Debug { fn to_slice(&self) -> Cow<'_, [Syllable]>; fn to_bytes(&self) -> Vec { @@ -304,7 +306,7 @@ impl Display for Syllable { } } -/// TODO: docs +/// A syllable builder can be used to construct syllables at compile time. #[derive(Debug)] pub struct SyllableBuilder { value: u16, @@ -318,14 +320,14 @@ impl Default for SyllableBuilder { } impl SyllableBuilder { - /// TODO: docs + /// Creates a new syllable builder. pub const fn new() -> SyllableBuilder { SyllableBuilder { value: Syllable::EMPTY_PATTERN, step: 0, } } - /// TODO: docs + /// Inserts syllable components and checks they follow correct order. #[allow(clippy::unusual_byte_groupings)] pub const fn insert( mut self, @@ -379,7 +381,7 @@ impl SyllableBuilder { }; Ok(self) } - /// TODO: docs + /// Builds the syllable. pub const fn build(self) -> Syllable { Syllable { value: match NonZeroU16::new(self.value) { @@ -390,7 +392,7 @@ impl SyllableBuilder { } } -/// TODO: docs +/// Errors during decoding a syllable from a u16. #[derive(Clone, Debug, PartialEq, Eq)] pub struct DecodeSyllableError; @@ -402,6 +404,7 @@ impl Display for DecodeSyllableError { impl Error for DecodeSyllableError {} +/// Errors when parsing a str to a syllable. #[derive(Clone, Debug, PartialEq, Eq)] #[non_exhaustive] pub enum SyllableErrorKind { @@ -413,6 +416,7 @@ pub enum SyllableErrorKind { InvalidBopomofo, } +/// Errors when building a new syllable. #[derive(Clone, Debug, PartialEq, Eq)] pub struct BuildSyllableError { kind: SyllableErrorKind, @@ -457,6 +461,7 @@ impl Display for BuildSyllableError { impl Error for BuildSyllableError {} +/// Errors when parsing a str to a syllable. #[derive(Clone, Debug, PartialEq, Eq)] pub struct ParseSyllableError { kind: SyllableErrorKind,