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