1use std::ffi::{CString, c_char};
24
25use crate::{Candidates, Error};
26
27pub struct CharsetDetector {
28 pub(crate) ptr: sys::uchardet_t,
29 pub(crate) external_error_occurred: bool,
30}
31
32impl Default for CharsetDetector {
33 #[inline]
34 fn default() -> Self {
35 Self::new()
36 }
37}
38
39impl CharsetDetector {
40 pub fn new() -> CharsetDetector {
41 let ptr = unsafe { sys::uchardet_new() };
42 debug_assert!(!ptr.is_null());
43 CharsetDetector {
44 ptr,
45 external_error_occurred: false,
46 }
47 }
48
49 pub fn feed_data(&mut self, data: impl AsRef<[u8]>) -> Result<(), Error> {
50 let data = data.as_ref();
51 let ret = unsafe {
52 sys::uchardet_handle_data(self.ptr, data.as_ptr() as *const c_char, data.len())
53 };
54 if ret == 0 {
55 Ok(())
56 } else {
57 self.external_error_occurred = true;
58 Err(unsafe { Error::from_ret(ret) })
59 }
60 }
61
62 pub fn reset(&mut self) {
63 self.external_error_occurred = false;
64 unsafe { sys::uchardet_reset(self.ptr) };
65 }
66
67 pub fn detect(self) -> Candidates {
68 unsafe {
69 sys::uchardet_data_end(self.ptr);
70 };
71 let n_candidates = unsafe { sys::uchardet_get_n_candidates(self.ptr) };
72 Candidates {
73 detector: self,
74 n_candidates,
75 }
76 }
77
78 pub fn detect_data(data: impl AsRef<[u8]>) -> Result<Candidates, Error> {
79 let mut detector = CharsetDetector::new();
80 detector.feed_data(data.as_ref())?;
81 Ok(detector.detect())
82 }
83
84 pub fn weigh_language(&mut self, language: &str, weight: f32) -> Result<(), Error> {
85 let c_lang = CString::new(language)?;
86 unsafe {
87 sys::uchardet_weigh_language(self.ptr, c_lang.as_ptr(), weight);
88 }
89 Ok(())
90 }
91
92 pub fn set_default_weight(&mut self, weight: f32) {
93 unsafe { sys::uchardet_set_default_weight(self.ptr, weight) }
94 }
95
96 pub fn external_error_occurred(&self) -> bool {
97 self.external_error_occurred
98 }
99}
100
101impl Drop for CharsetDetector {
102 fn drop(&mut self) {
103 unsafe { sys::uchardet_delete(self.ptr) };
104 }
105}