1use crate::utf8_decode::{decode_utf8, DecodeError, REPLACEMENT_CHARACTER};
10use crate::{fmt, IncompleteUtf8};
11use crate::{Atomic, Atomicity, Tendril};
12
13use std::borrow::Cow;
14use std::fs::File;
15use std::io;
16use std::marker::PhantomData;
17use std::path::Path;
18
19#[cfg(feature = "encoding_rs")]
20use encoding_rs::{self, DecoderResult};
21
22pub trait TendrilSink<F, A = Atomic>
31where
32 F: fmt::Format,
33 A: Atomicity,
34{
35 fn process(&mut self, t: Tendril<F, A>);
37
38 fn error(&mut self, desc: Cow<'static, str>);
40
41 type Output;
43
44 fn finish(self) -> Self::Output;
46
47 fn one<T>(mut self, t: T) -> Self::Output
49 where
50 Self: Sized,
51 T: Into<Tendril<F, A>>,
52 {
53 self.process(t.into());
54 self.finish()
55 }
56
57 fn from_iter<I>(mut self, i: I) -> Self::Output
59 where
60 Self: Sized,
61 I: IntoIterator,
62 I::Item: Into<Tendril<F, A>>,
63 {
64 for t in i {
65 self.process(t.into())
66 }
67 self.finish()
68 }
69
70 fn read_from<R>(mut self, r: &mut R) -> io::Result<Self::Output>
73 where
74 Self: Sized,
75 R: io::Read,
76 F: fmt::SliceFormat<Slice = [u8]>,
77 {
78 const BUFFER_SIZE: u32 = 4 * 1024;
79 loop {
80 let mut tendril = Tendril::<fmt::Bytes, A>::new();
81 tendril.extend_with_byte(BUFFER_SIZE, 0);
82 loop {
83 match r.read(&mut tendril) {
84 Ok(0) => return Ok(self.finish()),
85 Ok(n) => {
86 tendril.pop_back(BUFFER_SIZE - n as u32);
87 self.process(unsafe { tendril.reinterpret_without_validating() });
88 break;
89 },
90 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {},
91 Err(e) => return Err(e),
92 }
93 }
94 }
95 }
96
97 fn from_file<P>(self, path: P) -> io::Result<Self::Output>
100 where
101 Self: Sized,
102 P: AsRef<Path>,
103 F: fmt::SliceFormat<Slice = [u8]>,
104 {
105 self.read_from(&mut File::open(path)?)
106 }
107}
108
109pub struct Utf8LossyDecoder<Sink, A = Atomic>
116where
117 Sink: TendrilSink<fmt::UTF8, A>,
118 A: Atomicity,
119{
120 pub inner_sink: Sink,
121 incomplete: Option<IncompleteUtf8>,
122 marker: PhantomData<A>,
123}
124
125impl<Sink, A> Utf8LossyDecoder<Sink, A>
126where
127 Sink: TendrilSink<fmt::UTF8, A>,
128 A: Atomicity,
129{
130 #[inline]
132 pub fn new(inner_sink: Sink) -> Self {
133 Utf8LossyDecoder {
134 inner_sink,
135 incomplete: None,
136 marker: PhantomData,
137 }
138 }
139}
140
141impl<Sink, A> TendrilSink<fmt::Bytes, A> for Utf8LossyDecoder<Sink, A>
142where
143 Sink: TendrilSink<fmt::UTF8, A>,
144 A: Atomicity,
145{
146 #[inline]
147 fn process(&mut self, mut bytes: Tendril<fmt::Bytes, A>) {
148 if let Some(mut incomplete) = self.incomplete.take() {
150 let resume_at = incomplete
151 .try_to_complete_codepoint(&bytes)
152 .map(|(result, rest)| {
153 match result {
154 Ok(decoded_string) => {
155 self.inner_sink.process(Tendril::from_slice(decoded_string))
156 },
157 Err(_) => {
158 self.inner_sink.error("invalid byte sequence".into());
159 self.inner_sink
160 .process(Tendril::from_slice(REPLACEMENT_CHARACTER));
161 },
162 }
163 bytes.len() - rest.len()
164 });
165 match resume_at {
166 None => {
167 self.incomplete = Some(incomplete);
168 return;
169 },
170 Some(resume_at) => bytes.pop_front(resume_at as u32),
171 }
172 }
173 while !bytes.is_empty() {
174 let unborrowed_result = match decode_utf8(&bytes) {
175 Ok(s) => {
176 debug_assert!(s.as_ptr() == bytes.as_ptr());
177 debug_assert!(s.len() == bytes.len());
178 Ok(())
179 },
180 Err(DecodeError::Invalid {
181 valid_prefix,
182 invalid_sequence,
183 ..
184 }) => {
185 debug_assert!(valid_prefix.as_ptr() == bytes.as_ptr());
186 debug_assert!(valid_prefix.len() <= bytes.len());
187 Err((
188 valid_prefix.len(),
189 Err(valid_prefix.len() + invalid_sequence.len()),
190 ))
191 },
192 Err(DecodeError::Incomplete {
193 valid_prefix,
194 incomplete_suffix,
195 }) => {
196 debug_assert!(valid_prefix.as_ptr() == bytes.as_ptr());
197 debug_assert!(valid_prefix.len() <= bytes.len());
198 Err((valid_prefix.len(), Ok(incomplete_suffix)))
199 },
200 };
201 match unborrowed_result {
202 Ok(()) => {
203 unsafe {
204 self.inner_sink
205 .process(bytes.reinterpret_without_validating())
206 }
207 return;
208 },
209 Err((valid_len, and_then)) => {
210 if valid_len > 0 {
211 let subtendril = bytes.subtendril(0, valid_len as u32);
212 unsafe {
213 self.inner_sink
214 .process(subtendril.reinterpret_without_validating())
215 }
216 }
217 match and_then {
218 Ok(incomplete) => {
219 self.incomplete = Some(incomplete);
220 return;
221 },
222 Err(offset) => {
223 self.inner_sink.error("invalid byte sequence".into());
224 self.inner_sink
225 .process(Tendril::from_slice(REPLACEMENT_CHARACTER));
226 bytes.pop_front(offset as u32);
227 },
228 }
229 },
230 }
231 }
232 }
233
234 #[inline]
235 fn error(&mut self, desc: Cow<'static, str>) {
236 self.inner_sink.error(desc);
237 }
238
239 type Output = Sink::Output;
240
241 #[inline]
242 fn finish(mut self) -> Sink::Output {
243 if self.incomplete.is_some() {
244 self.inner_sink
245 .error("incomplete byte sequence at end of stream".into());
246 self.inner_sink
247 .process(Tendril::from_slice(REPLACEMENT_CHARACTER));
248 }
249 self.inner_sink.finish()
250 }
251}
252
253#[cfg(feature = "encoding_rs")]
259pub struct LossyDecoder<Sink, A = Atomic>
260where
261 Sink: TendrilSink<fmt::UTF8, A>,
262 A: Atomicity,
263{
264 inner: LossyDecoderInner<Sink, A>,
265}
266
267#[cfg(feature = "encoding_rs")]
268enum LossyDecoderInner<Sink, A>
269where
270 Sink: TendrilSink<fmt::UTF8, A>,
271 A: Atomicity,
272{
273 Utf8(Utf8LossyDecoder<Sink, A>),
274 #[cfg(feature = "encoding_rs")]
275 EncodingRs(encoding_rs::Decoder, Sink),
276}
277
278#[cfg(feature = "encoding_rs")]
279impl<Sink, A> LossyDecoder<Sink, A>
280where
281 Sink: TendrilSink<fmt::UTF8, A>,
282 A: Atomicity,
283{
284 #[cfg(feature = "encoding_rs")]
286 #[inline]
287 pub fn new_encoding_rs(encoding: &'static encoding_rs::Encoding, sink: Sink) -> Self {
288 if encoding == encoding_rs::UTF_8 {
289 return Self::utf8(sink);
290 }
291 Self {
292 inner: LossyDecoderInner::EncodingRs(encoding.new_decoder(), sink),
293 }
294 }
295
296 #[cfg(feature = "encoding_rs")]
301 #[inline]
302 pub fn new_from_encoding_rs_decoder(decoder: encoding_rs::Decoder, sink: Sink) -> Self {
303 Self {
304 inner: LossyDecoderInner::EncodingRs(decoder, sink),
305 }
306 }
307
308 #[inline]
313 pub fn utf8(sink: Sink) -> LossyDecoder<Sink, A> {
314 LossyDecoder {
315 inner: LossyDecoderInner::Utf8(Utf8LossyDecoder::new(sink)),
316 }
317 }
318
319 pub fn inner_sink(&self) -> &Sink {
321 match self.inner {
322 LossyDecoderInner::Utf8(ref utf8) => &utf8.inner_sink,
323 #[cfg(feature = "encoding_rs")]
324 LossyDecoderInner::EncodingRs(_, ref inner_sink) => inner_sink,
325 }
326 }
327
328 pub fn inner_sink_mut(&mut self) -> &mut Sink {
330 match self.inner {
331 LossyDecoderInner::Utf8(ref mut utf8) => &mut utf8.inner_sink,
332 #[cfg(feature = "encoding_rs")]
333 LossyDecoderInner::EncodingRs(_, ref mut inner_sink) => inner_sink,
334 }
335 }
336}
337
338#[cfg(feature = "encoding_rs")]
339impl<Sink, A> TendrilSink<fmt::Bytes, A> for LossyDecoder<Sink, A>
340where
341 Sink: TendrilSink<fmt::UTF8, A>,
342 A: Atomicity,
343{
344 #[inline]
345 fn process(&mut self, t: Tendril<fmt::Bytes, A>) {
346 match self.inner {
347 LossyDecoderInner::Utf8(ref mut utf8) => utf8.process(t),
348 #[cfg(feature = "encoding_rs")]
349 LossyDecoderInner::EncodingRs(ref mut decoder, ref mut sink) => {
350 if t.is_empty() {
351 return;
352 }
353 decode_to_sink(t, decoder, sink, false);
354 },
355 }
356 }
357
358 #[inline]
359 fn error(&mut self, desc: Cow<'static, str>) {
360 match self.inner {
361 LossyDecoderInner::Utf8(ref mut utf8) => utf8.error(desc),
362 #[cfg(feature = "encoding_rs")]
363 LossyDecoderInner::EncodingRs(_, ref mut sink) => sink.error(desc),
364 }
365 }
366
367 type Output = Sink::Output;
368
369 #[inline]
370 fn finish(self) -> Sink::Output {
371 match self.inner {
372 LossyDecoderInner::Utf8(utf8) => utf8.finish(),
373 #[cfg(feature = "encoding_rs")]
374 LossyDecoderInner::EncodingRs(mut decoder, mut sink) => {
375 decode_to_sink(Tendril::new(), &mut decoder, &mut sink, true);
376 sink.finish()
377 },
378 }
379 }
380}
381
382#[cfg(feature = "encoding_rs")]
383fn decode_to_sink<Sink, A>(
384 mut input: Tendril<fmt::Bytes, A>,
385 decoder: &mut encoding_rs::Decoder,
386 sink: &mut Sink,
387 last: bool,
388) where
389 Sink: TendrilSink<fmt::UTF8, A>,
390 A: Atomicity,
391{
392 loop {
393 let mut out = <Tendril<fmt::Bytes, A>>::new();
394 let max_len = decoder
395 .max_utf8_buffer_length_without_replacement(input.len())
396 .unwrap_or(8192);
397 unsafe {
398 out.push_uninitialized(max_len.min(8192) as u32);
399 }
400 let (result, bytes_read, bytes_written) =
401 decoder.decode_to_utf8_without_replacement(&input, &mut out, last);
402 if bytes_written > 0 {
403 sink.process(unsafe {
404 out.subtendril(0, bytes_written as u32)
405 .reinterpret_without_validating()
406 });
407 }
408 match result {
409 DecoderResult::InputEmpty => return,
410 DecoderResult::OutputFull => {},
411 DecoderResult::Malformed(_, _) => {
412 sink.error(Cow::Borrowed("invalid sequence"));
413 sink.process(Tendril::from_slice(REPLACEMENT_CHARACTER));
414 },
415 }
416 input.pop_front(bytes_read as u32);
417 if input.is_empty() {
418 return;
419 }
420 }
421}
422
423#[cfg(test)]
424mod test {
425 use super::{TendrilSink, Utf8LossyDecoder};
426 use crate::fmt;
427 use crate::{Atomic, Atomicity, NonAtomic, Tendril};
428 use std::borrow::Cow;
429
430 #[cfg(feature = "encoding_rs")]
431 use super::LossyDecoder;
432 #[cfg(feature = "encoding_rs")]
433 use crate::SliceExt;
434
435 #[cfg(feature = "encoding_rs")]
436 use encoding_rs as enc_rs;
437
438 struct Accumulate<A>
439 where
440 A: Atomicity,
441 {
442 tendrils: Vec<Tendril<fmt::UTF8, A>>,
443 errors: Vec<String>,
444 }
445
446 impl<A> Accumulate<A>
447 where
448 A: Atomicity,
449 {
450 fn new() -> Accumulate<A> {
451 Accumulate {
452 tendrils: vec![],
453 errors: vec![],
454 }
455 }
456 }
457
458 impl<A> TendrilSink<fmt::UTF8, A> for Accumulate<A>
459 where
460 A: Atomicity,
461 {
462 fn process(&mut self, t: Tendril<fmt::UTF8, A>) {
463 self.tendrils.push(t);
464 }
465
466 fn error(&mut self, desc: Cow<'static, str>) {
467 self.errors.push(desc.into_owned());
468 }
469
470 type Output = (Vec<Tendril<fmt::UTF8, A>>, Vec<String>);
471
472 fn finish(self) -> Self::Output {
473 (self.tendrils, self.errors)
474 }
475 }
476
477 fn check_utf8(input: &[&[u8]], expected: &[&str], errs: usize) {
478 let decoder = Utf8LossyDecoder::new(Accumulate::<NonAtomic>::new());
479 let (tendrils, errors) = decoder.from_iter(input.iter().cloned());
480 assert_eq!(
481 expected,
482 &*tendrils.iter().map(|t| &**t).collect::<Vec<_>>()
483 );
484 assert_eq!(errs, errors.len());
485 }
486
487 #[test]
488 fn utf8() {
489 check_utf8(&[], &[], 0);
490 check_utf8(&[b""], &[], 0);
491 check_utf8(&[b"xyz"], &["xyz"], 0);
492 check_utf8(&[b"x", b"y", b"z"], &["x", "y", "z"], 0);
493
494 check_utf8(&[b"xy\xEA\x99\xAEzw"], &["xy\u{a66e}zw"], 0);
495 check_utf8(&[b"xy\xEA", b"\x99\xAEzw"], &["xy", "\u{a66e}z", "w"], 0);
496 check_utf8(&[b"xy\xEA\x99", b"\xAEzw"], &["xy", "\u{a66e}z", "w"], 0);
497 check_utf8(
498 &[b"xy\xEA", b"\x99", b"\xAEzw"],
499 &["xy", "\u{a66e}z", "w"],
500 0,
501 );
502 check_utf8(&[b"\xEA", b"", b"\x99", b"", b"\xAE"], &["\u{a66e}"], 0);
503 check_utf8(
504 &[b"", b"\xEA", b"", b"\x99", b"", b"\xAE", b""],
505 &["\u{a66e}"],
506 0,
507 );
508
509 check_utf8(
510 &[b"xy\xEA", b"\xFF", b"\x99\xAEz"],
511 &["xy", "\u{fffd}", "\u{fffd}", "\u{fffd}", "\u{fffd}", "z"],
512 4,
513 );
514 check_utf8(
515 &[b"xy\xEA\x99", b"\xFFz"],
516 &["xy", "\u{fffd}", "\u{fffd}", "z"],
517 2,
518 );
519
520 check_utf8(&[b"\xC5\x91\xC5\x91\xC5\x91"], &["őőő"], 0);
521 check_utf8(
522 &[b"\xC5\x91", b"\xC5\x91", b"\xC5\x91"],
523 &["ő", "ő", "ő"],
524 0,
525 );
526 check_utf8(
527 &[b"\xC5", b"\x91\xC5", b"\x91\xC5", b"\x91"],
528 &["ő", "ő", "ő"],
529 0,
530 );
531 check_utf8(
532 &[b"\xC5", b"\x91\xff", b"\x91\xC5", b"\x91"],
533 &["ő", "\u{fffd}", "\u{fffd}", "ő"],
534 2,
535 );
536
537 check_utf8(&[b"\xC0"], &["\u{fffd}"], 1);
539 check_utf8(&[b"\xEA\x99"], &["\u{fffd}"], 1);
540 }
541
542 #[cfg(feature = "encoding_rs")]
543 fn check_decode(
544 mut decoder: LossyDecoder<Accumulate<Atomic>>,
545 input: &[&[u8]],
546 expected: &str,
547 errs: usize,
548 ) {
549 for x in input {
550 decoder.process(x.to_tendril());
551 }
552 let (tendrils, errors) = decoder.finish();
553 let mut tendril: Tendril<fmt::UTF8> = Tendril::new();
554 for t in tendrils {
555 tendril.push_tendril(&t);
556 }
557 assert_eq!(expected, &*tendril);
558 assert_eq!(errs, errors.len());
559 }
560
561 #[cfg(feature = "encoding_rs")]
562 pub type Tests = &'static [(&'static [&'static [u8]], &'static str, usize)];
563
564 #[cfg(feature = "encoding_rs")]
565 const UTF_8: Tests = &[
566 (&[], "", 0),
567 (&[b""], "", 0),
568 (&[b"xyz"], "xyz", 0),
569 (&[b"x", b"y", b"z"], "xyz", 0),
570 (&[b"\xEA\x99\xAE"], "\u{a66e}", 0),
571 (&[b"\xEA", b"\x99\xAE"], "\u{a66e}", 0),
572 (&[b"\xEA\x99", b"\xAE"], "\u{a66e}", 0),
573 (&[b"\xEA", b"\x99", b"\xAE"], "\u{a66e}", 0),
574 (&[b"\xEA", b"", b"\x99", b"", b"\xAE"], "\u{a66e}", 0),
575 (
576 &[b"", b"\xEA", b"", b"\x99", b"", b"\xAE", b""],
577 "\u{a66e}",
578 0,
579 ),
580 (&[b"xy\xEA", b"\x99\xAEz"], "xy\u{a66e}z", 0),
581 (
582 &[b"xy\xEA", b"\xFF", b"\x99\xAEz"],
583 "xy\u{fffd}\u{fffd}\u{fffd}\u{fffd}z",
584 4,
585 ),
586 (&[b"xy\xEA\x99", b"\xFFz"], "xy\u{fffd}\u{fffd}z", 2),
587 (&[b"\xC0"], "\u{fffd}", 1),
589 (&[b"\xEA\x99"], "\u{fffd}", 1),
590 ];
591
592 #[cfg(feature = "encoding_rs")]
593 #[test]
594 fn decode_utf8_encoding_rs() {
595 for &(input, expected, errs) in UTF_8 {
596 let decoder = LossyDecoder::new_encoding_rs(enc_rs::UTF_8, Accumulate::new());
597 check_decode(decoder, input, expected, errs);
598 }
599 }
600
601 #[cfg(feature = "encoding_rs")]
602 const KOI8_U: Tests = &[
603 (&[b"\xfc\xce\xc5\xd2\xc7\xc9\xd1"], "Энергия", 0),
604 (&[b"\xfc\xce", b"\xc5\xd2\xc7\xc9\xd1"], "Энергия", 0),
605 (&[b"\xfc\xce", b"\xc5\xd2\xc7", b"\xc9\xd1"], "Энергия", 0),
606 (
607 &[b"\xfc\xce", b"", b"\xc5\xd2\xc7", b"\xc9\xd1", b""],
608 "Энергия",
609 0,
610 ),
611 ];
612
613 #[cfg(feature = "encoding_rs")]
614 #[test]
615 fn decode_koi8_u_encoding_rs() {
616 for &(input, expected, errs) in KOI8_U {
617 let decoder = LossyDecoder::new_encoding_rs(enc_rs::KOI8_U, Accumulate::new());
618 check_decode(decoder, input, expected, errs);
619 }
620 }
621
622 #[cfg(feature = "encoding_rs")]
623 const WINDOWS_949: Tests = &[
624 (&[], "", 0),
625 (&[b""], "", 0),
626 (&[b"\xbe\xc8\xb3\xe7"], "안녕", 0),
627 (&[b"\xbe", b"\xc8\xb3\xe7"], "안녕", 0),
628 (&[b"\xbe", b"", b"\xc8\xb3\xe7"], "안녕", 0),
629 (
630 &[b"\xbe\xc8\xb3\xe7\xc7\xcf\xbc\xbc\xbf\xe4"],
631 "안녕하세요",
632 0,
633 ),
634 (&[b"\xbe\xc8\xb3\xe7\xc7"], "안녕\u{fffd}", 1),
635 (&[b"\xbe", b"", b"\xc8\xb3"], "안\u{fffd}", 1),
636 (&[b"\xbe\x28\xb3\xe7"], "\u{fffd}(녕", 1),
637 ];
638
639 #[cfg(feature = "encoding_rs")]
640 #[test]
641 fn decode_windows_949_encoding_rs() {
642 for &(input, expected, errs) in WINDOWS_949 {
643 let decoder = LossyDecoder::new_encoding_rs(enc_rs::EUC_KR, Accumulate::new());
644 check_decode(decoder, input, expected, errs);
645 }
646 }
647
648 #[test]
649 fn read_from() {
650 let decoder = Utf8LossyDecoder::new(Accumulate::<NonAtomic>::new());
651 let mut bytes: &[u8] = b"foo\xffbar";
652 let (tendrils, errors) = decoder.read_from(&mut bytes).unwrap();
653 assert_eq!(
654 &*tendrils.iter().map(|t| &**t).collect::<Vec<_>>(),
655 &["foo", "\u{FFFD}", "bar"]
656 );
657 assert_eq!(errors, &["invalid byte sequence"]);
658 }
659}