rust_macios/natural_language/
nl_language_recognizer.rs

1//! The language of a body of text.
2
3use objc::{msg_send, sel, sel_impl};
4
5use crate::{
6    foundation::{NSArray, NSDictionary, NSNumber, NSString, UInt},
7    object,
8    objective_c_runtime::{
9        macros::interface_impl,
10        traits::{FromId, PNSObject},
11    },
12    utils::to_optional,
13};
14
15use super::NLLanguage;
16
17object! {
18    /// The language of a body of text.
19    unsafe pub struct NLLanguageRecognizer;
20}
21
22#[interface_impl(NSObject)]
23impl NLLanguageRecognizer {
24    /* Creating a Recognizer
25     */
26
27    /// Creates a recognizer that you can customize.
28    #[method]
29    pub fn init(&mut self) -> Self
30    where
31        Self: Sized + FromId,
32    {
33        unsafe { Self::from_id(msg_send![Self::m_class(), init]) }
34    }
35
36    /* Determining the Language
37     */
38
39    /// Finds the most likely language of a piece of text.
40    #[method]
41    pub fn dominant_language_for_string(&self, string: &NSString) -> Option<NLLanguage> {
42        unsafe {
43            to_optional(msg_send![
44                Self::m_class(),
45                dominantLanguageForString: string.m_self()
46            ])
47        }
48    }
49
50    /// Analyzes the piece of text to determine its dominant language.
51    #[method]
52    pub fn process_string(&mut self, string: &NSString) {
53        unsafe { msg_send![self.m_self(), processString: string.m_self()] }
54    }
55
56    /// The most likely language for the processed text.
57    #[method]
58    pub fn dominant_language(&self) -> Option<NSString> {
59        unsafe { to_optional(msg_send![self.m_self(), dominantLanguage]) }
60    }
61
62    /// Generates the probabilities of possible languages for the processed text.
63    #[method]
64    pub fn language_hypotheses_with_maximum(
65        &self,
66        max_hypotheses: UInt,
67    ) -> NSDictionary<NLLanguage, NSNumber> {
68        unsafe {
69            NSDictionary::from_id(msg_send![
70                self.m_self(),
71                languageHypothesesWithMaximum: max_hypotheses
72            ])
73        }
74    }
75
76    /// Resets the recognizer to its initial state.
77    #[method]
78    pub fn reset(&mut self) {
79        unsafe { msg_send![self.m_self(), reset] }
80    }
81
82    /* Guiding the Recognizer
83     */
84
85    /// A dictionary that maps languages to their probabilities in the language identification process.
86    #[property]
87    pub fn language_hints(&self) -> NSDictionary<NLLanguage, NSNumber> {
88        unsafe { NSDictionary::from_id(msg_send![self.m_self(), languageHints]) }
89    }
90
91    /// Sets a dictionary that maps languages to their probabilities in the language identification process.
92    #[property]
93    pub fn set_language_hints(&mut self, language_hints: &NSDictionary<NLLanguage, NSNumber>) {
94        unsafe { msg_send![self.m_self(), setLanguageHints: language_hints.m_self()] }
95    }
96
97    /// Limits the set of possible languages that the recognizer will return.
98    #[property]
99    pub fn language_constraints(&self) -> NSArray<NLLanguage> {
100        unsafe { NSArray::from_id(msg_send![self.m_self(), languageConstraints]) }
101    }
102
103    /// Sets the limits  of the set of possible languages that the recognizer will return.
104    #[property]
105    pub fn set_language_constraints(&mut self, language_constraints: &NSArray<NLLanguage>) {
106        unsafe { msg_send![self.m_self(), setLanguageConstraints: language_constraints.m_self()] }
107    }
108}
109
110impl Default for NLLanguageRecognizer {
111    fn default() -> Self {
112        Self::m_new()
113    }
114}
115
116#[cfg(test)]
117mod tests {
118    use crate::{natural_language::English, nsarray, nsdictionary};
119
120    use super::*;
121
122    #[test]
123    fn test_dominant_language() {
124        let mut lr = NLLanguageRecognizer::default();
125        lr.process_string(&"This is a test.".into());
126        let lang = lr.dominant_language();
127        assert_eq!(lang.unwrap_or_default(), "en");
128    }
129
130    #[test]
131    fn test_lang_hints() {
132        let mut lr = NLLanguageRecognizer::default();
133        lr.process_string(&"This is a test.".into());
134        lr.set_language_hints(&nsdictionary!(
135            unsafe {English.clone()} => NSNumber::from(1.0),
136        ));
137        let lang_hints = lr.language_hints();
138
139        assert_eq!(lang_hints.count(), 1);
140        assert_eq!(
141            lang_hints.object_for_key(unsafe { English.clone() }),
142            Some(NSNumber::from(1.0))
143        );
144
145        lr.set_language_hints(&nsdictionary!(
146            unsafe {English.clone()} => NSNumber::from(1.0),
147            unsafe {English.clone()} => NSNumber::from(2.0),
148        ));
149    }
150
151    #[test]
152    fn test_lang_constraints() {
153        let mut lr = NLLanguageRecognizer::default();
154        lr.process_string(&"This is a test.".into());
155        lr.set_language_constraints(&nsarray!(unsafe { English.clone() }));
156        let lang_constraints = lr.language_constraints();
157
158        assert_eq!(lang_constraints.count(), 1);
159    }
160
161    #[test]
162    fn test_reset() {
163        let mut lr = NLLanguageRecognizer::default();
164        lr.process_string(&"This is a test.".into());
165        let mut lang = lr.dominant_language();
166        assert_eq!(lang.unwrap_or_default(), "en");
167        lr.reset();
168        lr.process_string(&"Det här är ett test".into());
169        lang = lr.dominant_language();
170        assert_eq!(lang.unwrap_or_default(), "sv");
171    }
172
173    #[test]
174    fn test_lang_hypotheses() {
175        let mut lr = NLLanguageRecognizer::default();
176        lr.process_string(&"This is a test.".into());
177        let lang_hypotheses = lr.language_hypotheses_with_maximum(1);
178        assert_eq!(lang_hypotheses.count(), 1);
179    }
180
181    #[test]
182    fn test_dominant_language_for_string() {
183        let mut lr = NLLanguageRecognizer::default();
184        lr.process_string(&"This is a test.".into());
185        let lang = lr.dominant_language_for_string(&"This is a test.".into());
186        assert_eq!(lang.unwrap_or_default(), "en");
187    }
188}