1use std::collections::HashMap;
15use std::io::{self, BufReader, IsTerminal, Read, Seek, Write};
16
17use crate::object::EntityId;
18
19#[derive(Debug)]
21pub enum RleState {
22 Init,
24 Literal { remaining: u16 },
26 Repeat { byte: u8, remaining: u16 },
28 Eod,
30}
31
32pub enum FilterKind {
34 ASCIIHexDecode,
36 ASCII85Decode {
38 group: Vec<u8>,
39 },
40 RunLengthDecode {
41 state: RleState,
42 },
43 FlateDecode {
44 decompressor: flate2::Decompress,
45 raw_buf: Vec<u8>,
46 predictor: u8,
47 columns: u32,
48 colors: u32,
49 bpc: u32,
50 prev_row: Vec<u8>,
51 },
52 LZWDecode {
53 decoder: weezl::decode::Decoder,
54 raw_buf: Vec<u8>,
55 },
56 DCTDecode {
58 decoded: bool,
59 color_transform: Option<bool>,
60 },
61 SubFileDecode {
62 eod_string: Vec<u8>,
63 eod_count: i32,
64 bytes_remaining: Option<i64>,
65 },
66 CCITTFaxDecode {
68 decoded: bool,
70 k: i32,
72 columns: u32,
74 rows: u32,
76 end_of_line: bool,
78 encoded_byte_align: bool,
80 end_of_block: bool,
82 black_is1: bool,
84 },
85 EexecDecode {
87 r: u16,
89 is_hex: Option<bool>,
91 skip_count: u32,
93 hex_leftover: Option<u8>,
95 },
96 ASCIIHexEncode,
99 ASCII85Encode {
101 buf: Vec<u8>,
103 col: usize,
105 },
106 RunLengthEncode {
109 pending: Vec<u8>,
111 run_byte: Option<u8>,
113 run_count: usize,
115 },
116 FlateEncode {
118 compressor: flate2::Compress,
119 predictor: u8,
120 columns: u32,
121 colors: u32,
122 bpc: u32,
123 row_width: usize,
125 bpp: usize,
127 encode_buf: Vec<u8>,
129 prev_row: Vec<u8>,
131 },
132 LZWEncode {
134 encoder: weezl::encode::Encoder,
135 },
136 NullEncode,
138 DCTEncode {
140 buf: Vec<u8>,
141 columns: u32,
142 rows: u32,
143 colors: u32,
144 quality: u8,
145 color_transform: bool,
146 },
147}
148
149pub struct FilterState {
151 pub kind: FilterKind,
152 pub source: EntityId,
153 pub output_buf: Vec<u8>,
154 pub output_pos: usize,
155 pub putback: Vec<u8>,
156 pub eof: bool,
157 pub bytes_read: u64,
159}
160
161pub enum FileHandle {
163 Real(BufReader<std::fs::File>),
165 Stdin,
167 Stdout,
169 Stderr,
171 Closed,
173 Filter(Box<FilterState>),
175 StringSource { data: Vec<u8>, pos: usize },
177}
178
179fn rle_emit_literals(pending: &[u8]) -> Vec<u8> {
183 if pending.is_empty() {
184 return Vec::new();
185 }
186 let mut out = Vec::with_capacity(pending.len() + 1);
187 out.push((pending.len() - 1) as u8);
188 out.extend_from_slice(pending);
189 out
190}
191
192fn rle_emit_repeat(byte: u8, count: usize) -> [u8; 2] {
194 [(257 - count) as u8, byte]
195}
196
197pub struct FileEntry {
199 pub handle: FileHandle,
200 pub name: String,
201 pub mode: String,
202 pub line_num: u32,
204 pub pending_newlines: u32,
208}
209
210pub struct FileStore {
212 files: Vec<FileEntry>,
213 embedded_files: HashMap<String, &'static [u8]>,
216}
217
218pub const FILE_STDIN: EntityId = EntityId(0);
220pub const FILE_STDOUT: EntityId = EntityId(1);
221pub const FILE_STDERR: EntityId = EntityId(2);
222
223impl FileStore {
224 pub fn new() -> Self {
226 let mut store = Self {
227 files: Vec::new(),
228 embedded_files: HashMap::new(),
229 };
230 store.files.push(FileEntry {
232 handle: FileHandle::Stdin,
233 name: "%stdin".to_string(),
234 mode: "r".to_string(),
235 line_num: 1,
236 pending_newlines: 0,
237 });
238 store.files.push(FileEntry {
239 handle: FileHandle::Stdout,
240 name: "%stdout".to_string(),
241 mode: "w".to_string(),
242 line_num: 1,
243 pending_newlines: 0,
244 });
245 store.files.push(FileEntry {
246 handle: FileHandle::Stderr,
247 name: "%stderr".to_string(),
248 mode: "w".to_string(),
249 line_num: 1,
250 pending_newlines: 0,
251 });
252 store
253 }
254
255 pub fn add_embedded_file(&mut self, path: &str, data: &'static [u8]) {
257 self.embedded_files.insert(path.to_string(), data);
258 }
259
260 pub fn get_embedded_file(&self, path: &str) -> Option<&'static [u8]> {
265 if let Some(data) = self.embedded_files.get(path) {
266 return Some(*data);
267 }
268 let normalized = path.trim_start_matches('/').replace("//", "/");
270 if normalized != path {
271 return self.embedded_files.get(normalized.as_str()).copied();
272 }
273 None
274 }
275
276 pub fn open(&mut self, name: &str, mode: &str) -> io::Result<EntityId> {
280 match name {
282 "%stdin" => {
283 if mode != "r" {
284 return Err(io::Error::new(
285 io::ErrorKind::PermissionDenied,
286 "%stdin is read-only",
287 ));
288 }
289 return Ok(FILE_STDIN);
290 }
291 "%stdout" => {
292 if mode != "w" {
293 return Err(io::Error::new(
294 io::ErrorKind::PermissionDenied,
295 "%stdout is write-only",
296 ));
297 }
298 return Ok(FILE_STDOUT);
299 }
300 "%stderr" => {
301 if mode != "w" {
302 return Err(io::Error::new(
303 io::ErrorKind::PermissionDenied,
304 "%stderr is write-only",
305 ));
306 }
307 return Ok(FILE_STDERR);
308 }
309 "%lineedit" | "%statementedit" => {
310 if mode != "r" {
311 return Err(io::Error::new(
312 io::ErrorKind::PermissionDenied,
313 "read-only special file",
314 ));
315 }
316 let mut line = String::new();
318 let n = io::stdin().read_line(&mut line)?;
319 if n == 0 {
320 return Err(io::Error::new(io::ErrorKind::NotFound, "EOF on stdin"));
322 }
323 if line.ends_with('\n') {
324 line.pop();
325 if line.ends_with('\r') {
326 line.pop();
327 }
328 }
329 return Ok(self.create_string_source(line.into_bytes()));
330 }
331 _ => {}
332 }
333
334 if mode == "r"
336 && let Some(data) = self.embedded_files.get(name)
337 {
338 let id = EntityId(self.files.len() as u32);
339 self.files.push(FileEntry {
340 handle: FileHandle::StringSource {
341 data: data.to_vec(),
342 pos: 0,
343 },
344 name: name.to_string(),
345 mode: mode.to_string(),
346 line_num: 1,
347 pending_newlines: 0,
348 });
349 return Ok(id);
350 }
351
352 let file = match mode {
353 "r" => std::fs::File::open(name)?,
354 "w" => std::fs::File::create(name)?,
355 "a" => std::fs::OpenOptions::new()
356 .append(true)
357 .create(true)
358 .open(name)?,
359 "r+" => std::fs::OpenOptions::new()
360 .read(true)
361 .write(true)
362 .open(name)?,
363 _ => return Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid mode")),
364 };
365
366 let id = EntityId(self.files.len() as u32);
367 self.files.push(FileEntry {
368 handle: FileHandle::Real(BufReader::new(file)),
369 name: name.to_string(),
370 mode: mode.to_string(),
371 line_num: 1,
372 pending_newlines: 0,
373 });
374 Ok(id)
375 }
376
377 pub fn create_filter(&mut self, source: EntityId, kind: FilterKind) -> EntityId {
379 let id = EntityId(self.files.len() as u32);
380 self.files.push(FileEntry {
381 handle: FileHandle::Filter(Box::new(FilterState {
382 kind,
383 source,
384 output_buf: Vec::new(),
385 output_pos: 0,
386 putback: Vec::new(),
387 eof: false,
388 bytes_read: 0,
389 })),
390 name: "%filter".to_string(),
391 mode: "r".to_string(),
392 line_num: 1,
393 pending_newlines: 0,
394 });
395 id
396 }
397
398 pub fn create_filter_with_data(
400 &mut self,
401 source: EntityId,
402 kind: FilterKind,
403 data: Vec<u8>,
404 ) -> EntityId {
405 let id = EntityId(self.files.len() as u32);
406 self.files.push(FileEntry {
407 handle: FileHandle::Filter(Box::new(FilterState {
408 kind,
409 source,
410 output_buf: data,
411 output_pos: 0,
412 putback: Vec::new(),
413 eof: false,
414 bytes_read: 0,
415 })),
416 name: "%filter".to_string(),
417 mode: "r".to_string(),
418 line_num: 1,
419 pending_newlines: 0,
420 });
421 id
422 }
423
424 pub fn create_encode_filter(&mut self, target: EntityId, kind: FilterKind) -> EntityId {
426 let id = EntityId(self.files.len() as u32);
427 self.files.push(FileEntry {
428 handle: FileHandle::Filter(Box::new(FilterState {
429 kind,
430 source: target, output_buf: Vec::new(),
432 output_pos: 0,
433 putback: Vec::new(),
434 eof: false,
435 bytes_read: 0,
436 })),
437 name: "%filter".to_string(),
438 mode: "w".to_string(),
439 line_num: 1,
440 pending_newlines: 0,
441 });
442 id
443 }
444
445 pub fn create_string_source(&mut self, data: Vec<u8>) -> EntityId {
447 let id = EntityId(self.files.len() as u32);
448 self.files.push(FileEntry {
449 handle: FileHandle::StringSource { data, pos: 0 },
450 name: "%stringsource".to_string(),
451 mode: "r".to_string(),
452 line_num: 1,
453 pending_newlines: 0,
454 });
455 id
456 }
457
458 pub fn get_remaining_bytes(&self, entity: EntityId) -> &[u8] {
463 let entry = &self.files[entity.0 as usize];
464 match &entry.handle {
465 FileHandle::StringSource { data, pos } => &data[*pos..],
466 _ => &[],
467 }
468 }
469
470 pub fn advance_position(&mut self, entity: EntityId, n: usize) {
472 let entry = &mut self.files[entity.0 as usize];
473 if let FileHandle::StringSource { pos, .. } = &mut entry.handle {
474 *pos += n;
475 }
476 }
477
478 pub fn line_num(&self, entity: EntityId) -> u32 {
480 self.files[entity.0 as usize].line_num
481 }
482
483 pub fn add_pending_newlines(&mut self, entity: EntityId, count: u32) {
486 self.files[entity.0 as usize].pending_newlines += count;
487 }
488
489 pub fn flush_pending_newlines(&mut self, entity: EntityId) {
492 let entry = &mut self.files[entity.0 as usize];
493 entry.line_num += entry.pending_newlines;
494 entry.pending_newlines = 0;
495 }
496
497 pub fn close(&mut self, entity: EntityId) -> io::Result<()> {
499 let is_encode = matches!(
501 &self.files[entity.0 as usize].handle,
502 FileHandle::Filter(state) if state.kind.is_encode()
503 );
504 if is_encode {
505 return self.close_encode_filter(entity);
506 }
507
508 let entry = &mut self.files[entity.0 as usize];
509 match entry.handle {
510 FileHandle::Stdin | FileHandle::Stdout | FileHandle::Stderr => Ok(()),
511 FileHandle::Closed => Ok(()),
512 FileHandle::Filter(_) => {
513 entry.handle = FileHandle::Closed;
515 Ok(())
516 }
517 _ => {
518 entry.handle = FileHandle::Closed;
519 Ok(())
520 }
521 }
522 }
523
524 pub fn read_byte(&mut self, entity: EntityId) -> io::Result<Option<u8>> {
526 let entry = &mut self.files[entity.0 as usize];
527 match &mut entry.handle {
528 FileHandle::Real(f) => {
529 let mut buf = [0u8; 1];
530 let n = f.read(&mut buf)?;
531 if n == 0 { Ok(None) } else { Ok(Some(buf[0])) }
532 }
533 FileHandle::Stdin => {
534 if std::io::stdin().is_terminal() {
535 Ok(None) } else {
537 let mut buf = [0u8; 1];
538 let n = io::stdin().read(&mut buf)?;
539 if n == 0 { Ok(None) } else { Ok(Some(buf[0])) }
540 }
541 }
542 FileHandle::StringSource { data, pos } => {
543 if *pos < data.len() {
544 let b = data[*pos];
545 *pos += 1;
546 Ok(Some(b))
547 } else {
548 Ok(None)
549 }
550 }
551 FileHandle::Filter(_) => {
552 self.read_byte_filter(entity)
554 }
555 FileHandle::Closed => Ok(None), _ => Err(io::Error::other("not readable")),
557 }
558 }
559
560 fn read_byte_filter(&mut self, entity: EntityId) -> io::Result<Option<u8>> {
562 let entry = &mut self.files[entity.0 as usize];
563 let mut state = match std::mem::replace(&mut entry.handle, FileHandle::Closed) {
564 FileHandle::Filter(s) => s,
565 other => {
566 entry.handle = other;
567 return Err(io::Error::other("not a filter"));
568 }
569 };
570
571 if let Some(b) = state.putback.pop() {
573 state.bytes_read += 1;
574 self.files[entity.0 as usize].handle = FileHandle::Filter(state);
575 return Ok(Some(b));
576 }
577
578 if state.output_pos < state.output_buf.len() {
580 let b = state.output_buf[state.output_pos];
581 state.output_pos += 1;
582 state.bytes_read += 1;
583 self.files[entity.0 as usize].handle = FileHandle::Filter(state);
584 return Ok(Some(b));
585 }
586
587 if state.eof {
589 self.files[entity.0 as usize].handle = FileHandle::Filter(state);
590 return Ok(None);
591 }
592
593 self.refill_filter(&mut state)?;
595
596 let result = if state.output_pos < state.output_buf.len() {
597 let b = state.output_buf[state.output_pos];
598 state.output_pos += 1;
599 state.bytes_read += 1;
600 Ok(Some(b))
601 } else {
602 Ok(None)
603 };
604
605 self.files[entity.0 as usize].handle = FileHandle::Filter(state);
606 result
607 }
608
609 pub fn read_into(&mut self, entity: EntityId, buf: &mut [u8]) -> io::Result<usize> {
611 let entry = &mut self.files[entity.0 as usize];
612 match &mut entry.handle {
613 FileHandle::Real(f) => f.read(buf),
614 FileHandle::Stdin => {
615 if std::io::stdin().is_terminal() {
618 Ok(0)
619 } else {
620 io::stdin().read(buf)
621 }
622 }
623 FileHandle::StringSource { data, pos } => {
624 let remaining = data.len() - *pos;
625 let n = buf.len().min(remaining);
626 buf[..n].copy_from_slice(&data[*pos..*pos + n]);
627 *pos += n;
628 Ok(n)
629 }
630 FileHandle::Filter(_) => {
631 let mut count = 0;
633 for slot in buf.iter_mut() {
634 match self.read_byte(entity)? {
635 Some(b) => {
636 *slot = b;
637 count += 1;
638 }
639 None => break,
640 }
641 }
642 Ok(count)
643 }
644 FileHandle::Closed => Err(io::Error::other("file closed")),
645 _ => Err(io::Error::other("not readable")),
646 }
647 }
648
649 pub fn write_byte(&mut self, entity: EntityId, byte: u8) -> io::Result<()> {
651 self.write_from(entity, &[byte])
652 }
653
654 pub fn write_from(&mut self, entity: EntityId, buf: &[u8]) -> io::Result<()> {
656 let is_encode = matches!(
658 &self.files[entity.0 as usize].handle,
659 FileHandle::Filter(state) if state.kind.is_encode()
660 );
661 if is_encode {
662 return self.encode_write(entity, buf);
663 }
664 let entry = &mut self.files[entity.0 as usize];
665 match &mut entry.handle {
666 FileHandle::Real(f) => f.get_mut().write_all(buf),
667 FileHandle::Stdout => io::stdout().write_all(buf),
668 FileHandle::Stderr => io::stderr().write_all(buf),
669 FileHandle::Closed => Err(io::Error::other("file closed")),
670 _ => Err(io::Error::other("not writable")),
671 }
672 }
673
674 fn encode_write(&mut self, entity: EntityId, data: &[u8]) -> io::Result<()> {
676 let entry = &mut self.files[entity.0 as usize];
678 let mut state = match std::mem::replace(&mut entry.handle, FileHandle::Closed) {
679 FileHandle::Filter(s) => s,
680 other => {
681 entry.handle = other;
682 return Err(io::Error::other("not an encode filter"));
683 }
684 };
685
686 let target = state.source;
687 let result = match &mut state.kind {
688 FilterKind::ASCIIHexEncode => {
689 let mut hex = Vec::with_capacity(data.len() * 2);
691 for &b in data {
692 hex.push(b"0123456789ABCDEF"[(b >> 4) as usize]);
693 hex.push(b"0123456789ABCDEF"[(b & 0xF) as usize]);
694 }
695 self.write_from(target, &hex)
696 }
697 FilterKind::ASCII85Encode { buf, col } => {
698 let mut encoded = Vec::new();
699 for &byte in data {
700 buf.push(byte);
701 if buf.len() == 4 {
702 let val = u32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]);
703 if val == 0 {
704 encoded.push(b'z');
705 *col += 1;
706 } else {
707 let mut chars = [0u8; 5];
708 let mut v = val;
709 for c in chars.iter_mut().rev() {
710 *c = (v % 85) as u8 + b'!';
711 v /= 85;
712 }
713 encoded.extend_from_slice(&chars);
714 *col += 5;
715 }
716 buf.clear();
717 if *col >= 75 {
718 encoded.push(b'\n');
719 *col = 0;
720 }
721 }
722 }
723 if encoded.is_empty() {
724 Ok(())
725 } else {
726 self.write_from(target, &encoded)
727 }
728 }
729 FilterKind::RunLengthEncode {
730 pending,
731 run_byte,
732 run_count,
733 } => {
734 for &b in data {
736 if let Some(rb) = *run_byte {
737 if b == rb {
738 *run_count += 1;
739 if *run_count >= 128 {
740 let lit = rle_emit_literals(pending);
742 if !lit.is_empty() {
743 self.write_from(target, &lit)?;
744 pending.clear();
745 }
746 let rep = rle_emit_repeat(rb, 128);
747 self.write_from(target, &rep)?;
748 *run_byte = None;
749 *run_count = 0;
750 }
751 } else {
752 if *run_count >= 3 {
754 let lit = rle_emit_literals(pending);
756 if !lit.is_empty() {
757 self.write_from(target, &lit)?;
758 pending.clear();
759 }
760 let rep = rle_emit_repeat(rb, *run_count);
761 self.write_from(target, &rep)?;
762 } else {
763 for _ in 0..*run_count {
765 pending.push(rb);
766 }
767 if pending.len() >= 128 {
768 let lit = rle_emit_literals(pending);
769 self.write_from(target, &lit)?;
770 pending.clear();
771 }
772 }
773 *run_byte = Some(b);
774 *run_count = 1;
775 }
776 } else {
777 *run_byte = Some(b);
779 *run_count = 1;
780 }
781 }
782 Ok(())
783 }
784 FilterKind::FlateEncode {
785 compressor,
786 predictor,
787 row_width,
788 bpp,
789 encode_buf,
790 prev_row,
791 ..
792 } => {
793 if *predictor <= 1 {
794 flate_compress_data(compressor, data, |chunk| self.write_from(target, chunk))
796 } else {
797 encode_buf.extend_from_slice(data);
799 let rw = *row_width;
800 let pred = *predictor;
801 let bp = *bpp;
802 while encode_buf.len() >= rw {
803 let row: Vec<u8> = encode_buf.drain(..rw).collect();
804 let encoded = if pred >= 10 {
805 encode_png_row(&row, bp)
806 } else {
807 encode_tiff_row(&row, bp)
808 };
809 prev_row.copy_from_slice(&row);
810 flate_compress_data(compressor, &encoded, |chunk| {
811 self.write_from(target, chunk)
812 })?;
813 }
814 Ok(())
815 }
816 }
817 FilterKind::LZWEncode { encoder } => {
818 let mut out = vec![0u8; data.len() * 2 + 64];
819 let result = encoder.encode_bytes(data, &mut out);
820 if result.consumed_out > 0 {
821 self.write_from(target, &out[..result.consumed_out])?;
822 }
823 Ok(())
824 }
825 FilterKind::NullEncode => self.write_from(target, data),
826 FilterKind::DCTEncode { buf, .. } => {
827 buf.extend_from_slice(data);
831 Ok(())
832 }
833 _ => Err(io::Error::other("not an encode filter")),
834 };
835
836 self.files[entity.0 as usize].handle = FileHandle::Filter(state);
838 result
839 }
840
841 fn close_encode_filter(&mut self, entity: EntityId) -> io::Result<()> {
843 let entry = &mut self.files[entity.0 as usize];
845 let mut state = match std::mem::replace(&mut entry.handle, FileHandle::Closed) {
846 FileHandle::Filter(s) => s,
847 other => {
848 entry.handle = other;
849 return Ok(());
850 }
851 };
852
853 let target = state.source;
854 match &mut state.kind {
855 FilterKind::ASCIIHexEncode => {
856 self.write_from(target, b">")?;
857 }
858 FilterKind::ASCII85Encode { buf, .. } => {
859 if !buf.is_empty() {
861 let n = buf.len();
862 while buf.len() < 4 {
864 buf.push(0);
865 }
866 let val = u32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]);
867 let mut chars = [0u8; 5];
868 let mut v = val;
869 for c in chars.iter_mut().rev() {
870 *c = (v % 85) as u8 + b'!';
871 v /= 85;
872 }
873 self.write_from(target, &chars[..n + 1])?;
875 }
876 self.write_from(target, b"~>")?;
877 }
878 FilterKind::RunLengthEncode {
879 pending,
880 run_byte,
881 run_count,
882 } => {
883 if let Some(rb) = *run_byte {
885 if *run_count >= 3 {
886 let lit = rle_emit_literals(pending);
887 if !lit.is_empty() {
888 self.write_from(target, &lit)?;
889 }
890 let rep = rle_emit_repeat(rb, *run_count);
891 self.write_from(target, &rep)?;
892 } else {
893 for _ in 0..*run_count {
894 pending.push(rb);
895 }
896 let lit = rle_emit_literals(pending);
897 if !lit.is_empty() {
898 self.write_from(target, &lit)?;
899 }
900 }
901 } else if !pending.is_empty() {
902 let lit = rle_emit_literals(pending);
903 self.write_from(target, &lit)?;
904 }
905 self.write_from(target, &[128])?;
907 }
908 FilterKind::FlateEncode {
909 compressor,
910 predictor,
911 row_width,
912 bpp,
913 encode_buf,
914 ..
915 } => {
916 if *predictor > 1 && !encode_buf.is_empty() {
918 let rw = *row_width;
919 let pred = *predictor;
920 let bp = *bpp;
921 encode_buf.resize(rw, 0);
923 let row: Vec<u8> = std::mem::take(encode_buf);
924 let encoded = if pred >= 10 {
925 encode_png_row(&row, bp)
926 } else {
927 encode_tiff_row(&row, bp)
928 };
929 flate_compress_data(compressor, &encoded, |chunk| {
930 self.write_from(target, chunk)
931 })?;
932 }
933 let mut out = vec![0u8; 256];
935 loop {
936 let before_out = compressor.total_out() as usize;
937 let status = compressor
938 .compress(&[], &mut out, flate2::FlushCompress::Finish)
939 .map_err(|e| io::Error::other(e.to_string()))?;
940 let produced = compressor.total_out() as usize - before_out;
941 if produced > 0 {
942 self.write_from(target, &out[..produced])?;
943 }
944 if matches!(status, flate2::Status::StreamEnd) {
945 break;
946 }
947 }
948 }
949 FilterKind::LZWEncode { encoder } => {
950 encoder.finish();
952 let mut out = vec![0u8; 256];
953 loop {
954 let result = encoder.encode_bytes(&[], &mut out);
955 if result.consumed_out > 0 {
956 self.write_from(target, &out[..result.consumed_out])?;
957 }
958 if result.consumed_out == 0 {
959 break;
960 }
961 }
962 }
963 FilterKind::NullEncode => {}
964 FilterKind::DCTEncode {
965 buf,
966 columns,
967 rows,
968 colors,
969 quality,
970 color_transform,
971 } => {
972 let w = *columns as u16;
973 let h = *rows as u16;
974 let nc = *colors as u8;
975 let q = *quality;
976 let _ct = *color_transform;
977
978 let color_type = match nc {
980 1 => jpeg_encoder::ColorType::Luma,
981 3 => jpeg_encoder::ColorType::Rgb,
982 4 => jpeg_encoder::ColorType::Cmyk,
983 _ => jpeg_encoder::ColorType::Rgb,
984 };
985
986 let expected_len = w as usize * h as usize * nc as usize;
987 buf.resize(expected_len, 0);
989
990 let mut jpeg_data = Vec::new();
991 let encoder = jpeg_encoder::Encoder::new(&mut jpeg_data, q);
992 encoder
993 .encode(buf, w, h, color_type)
994 .map_err(|e| io::Error::other(format!("JPEG encode error: {e}")))?;
995 self.write_from(target, &jpeg_data)?;
996 }
997 _ => {}
998 }
999
1000 self.close(target)?;
1002
1003 Ok(())
1005 }
1006
1007 pub fn readline(&mut self, entity: EntityId, buf: &mut [u8]) -> io::Result<(usize, bool)> {
1009 let mut count = 0;
1010 let mut hit_newline = false;
1011 loop {
1012 if count >= buf.len() {
1013 break;
1014 }
1015 match self.read_byte(entity)? {
1016 None => break,
1017 Some(b'\n') => {
1018 hit_newline = true;
1019 break;
1020 }
1021 Some(b'\r') => {
1022 hit_newline = true;
1023 match self.read_byte(entity)? {
1025 Some(b'\n') => {} Some(other) => self.putback_bytes(entity, &[other]),
1027 None => {}
1028 }
1029 break;
1030 }
1031 Some(b) => {
1032 buf[count] = b;
1033 count += 1;
1034 }
1035 }
1036 }
1037 Ok((count, hit_newline))
1038 }
1039
1040 pub fn position(&mut self, entity: EntityId) -> io::Result<u64> {
1042 let entry = &mut self.files[entity.0 as usize];
1043 match &mut entry.handle {
1044 FileHandle::Real(f) => f.stream_position(),
1045 FileHandle::StringSource { pos, .. } => Ok(*pos as u64),
1046 FileHandle::Filter(state) => Ok(state.bytes_read),
1047 _ => Err(io::Error::other("not seekable")),
1048 }
1049 }
1050
1051 pub fn set_position(&mut self, entity: EntityId, pos: u64) -> io::Result<()> {
1053 let entry = &mut self.files[entity.0 as usize];
1054 match &mut entry.handle {
1055 FileHandle::Real(f) => {
1056 f.seek(io::SeekFrom::Start(pos))?;
1057 Ok(())
1058 }
1059 FileHandle::StringSource { data, pos: p } => {
1060 *p = (pos as usize).min(data.len());
1061 Ok(())
1062 }
1063 _ => Err(io::Error::other("not seekable")),
1064 }
1065 }
1066
1067 pub fn flush(&mut self, entity: EntityId) -> io::Result<()> {
1069 let entry = &self.files[entity.0 as usize];
1070 match &entry.handle {
1071 FileHandle::Real(_) => {
1072 let entry = &mut self.files[entity.0 as usize];
1073 if entry.mode.starts_with('r') {
1074 entry.handle = FileHandle::Closed;
1076 } else if let FileHandle::Real(f) = &mut entry.handle {
1077 f.get_mut().flush()?;
1078 }
1079 }
1080 FileHandle::Stdout => io::stdout().flush()?,
1081 FileHandle::Stderr => io::stderr().flush()?,
1082 FileHandle::Filter(_) => {
1083 let mut buf = [0u8; 4096];
1087 loop {
1088 match self.read_into(entity, &mut buf) {
1089 Ok(0) => break,
1090 Ok(_) => continue,
1091 Err(_) => break,
1092 }
1093 }
1094 }
1095 FileHandle::StringSource { .. } => {
1096 let entry = &mut self.files[entity.0 as usize];
1098 if let FileHandle::StringSource { data, pos } = &mut entry.handle {
1099 *pos = data.len();
1100 }
1101 }
1102 _ => {}
1103 }
1104 Ok(())
1105 }
1106
1107 pub fn is_open(&self, entity: EntityId) -> bool {
1109 if (entity.0 as usize) >= self.files.len() {
1110 return false;
1111 }
1112 !matches!(self.files[entity.0 as usize].handle, FileHandle::Closed)
1113 }
1114
1115 pub fn is_readable(&self, entity: EntityId) -> bool {
1117 if (entity.0 as usize) >= self.files.len() {
1118 return false;
1119 }
1120 !matches!(
1121 self.files[entity.0 as usize].handle,
1122 FileHandle::Closed | FileHandle::Stdout | FileHandle::Stderr
1123 )
1124 }
1125
1126 pub fn read_n_bytes(&mut self, entity: EntityId, n: usize) -> io::Result<Vec<u8>> {
1128 let mut result = Vec::with_capacity(n);
1129 for _ in 0..n {
1130 match self.read_byte(entity)? {
1131 Some(b) => result.push(b),
1132 None => return Err(io::Error::other("unexpected EOF")),
1133 }
1134 }
1135 Ok(result)
1136 }
1137
1138 pub fn putback_bytes(&mut self, entity: EntityId, bytes: &[u8]) {
1142 let entry = &mut self.files[entity.0 as usize];
1143 match &mut entry.handle {
1144 FileHandle::Filter(state) => {
1145 for &b in bytes.iter().rev() {
1147 state.putback.push(b);
1148 }
1149 }
1150 FileHandle::StringSource { pos, .. } => {
1151 *pos = pos.saturating_sub(bytes.len());
1152 }
1153 FileHandle::Real(f) => {
1154 let _ = f.seek(std::io::SeekFrom::Current(-(bytes.len() as i64)));
1156 }
1157 _ => {}
1158 }
1159 }
1160
1161 pub fn is_seekable(&self, entity: EntityId) -> bool {
1163 matches!(self.files[entity.0 as usize].handle, FileHandle::Real(_))
1164 }
1165
1166 pub fn bytes_available(&mut self, entity: EntityId) -> i32 {
1170 let entry = &mut self.files[entity.0 as usize];
1171 if entry.mode.starts_with('w') || entry.mode.starts_with('a') {
1173 return -1;
1174 }
1175 match &mut entry.handle {
1176 FileHandle::Real(f) => {
1177 if let Ok(cur) = f.stream_position() {
1178 if let Ok(end) = f.seek(io::SeekFrom::End(0)) {
1179 let _ = f.seek(io::SeekFrom::Start(cur));
1180 let remaining = end.saturating_sub(cur);
1181 if remaining == 0 {
1182 -1 } else {
1184 remaining.min(i32::MAX as u64) as i32
1185 }
1186 } else {
1187 -1
1188 }
1189 } else {
1190 -1
1191 }
1192 }
1193 FileHandle::StringSource { data, pos } => {
1194 let remaining = data.len() - *pos;
1195 if remaining == 0 { -1 } else { remaining as i32 }
1196 }
1197 FileHandle::Closed => -1,
1198 _ => -1,
1199 }
1200 }
1201
1202 pub fn name(&self, entity: EntityId) -> &str {
1204 &self.files[entity.0 as usize].name
1205 }
1206
1207 pub fn set_name(&mut self, entity: EntityId, name: String) {
1209 self.files[entity.0 as usize].name = name;
1210 }
1211
1212 pub fn mode(&self, entity: EntityId) -> &str {
1214 &self.files[entity.0 as usize].mode
1215 }
1216
1217 pub fn len(&self) -> usize {
1219 self.files.len()
1220 }
1221
1222 pub fn is_empty(&self) -> bool {
1224 self.files.is_empty()
1225 }
1226
1227 pub fn putback_byte(&mut self, entity: EntityId, byte: u8) {
1229 let entry = &mut self.files[entity.0 as usize];
1230 if let FileHandle::Filter(ref mut state) = entry.handle {
1231 state.putback.push(byte);
1232 }
1233 }
1234
1235 pub fn read_all(&mut self, entity: EntityId) -> io::Result<Vec<u8>> {
1237 let mut data = Vec::new();
1238 while let Some(b) = self.read_byte(entity)? {
1239 data.push(b);
1240 }
1241 Ok(data)
1242 }
1243
1244 fn refill_filter(&mut self, state: &mut FilterState) -> io::Result<()> {
1248 state.output_buf.clear();
1249 state.output_pos = 0;
1250
1251 match &mut state.kind {
1252 FilterKind::ASCIIHexDecode => {
1253 self.refill_ascii_hex(state.source, &mut state.output_buf, &mut state.eof)?;
1254 }
1255 FilterKind::ASCII85Decode { .. } => {
1256 let source = state.source;
1258 self.refill_ascii85(
1259 source,
1260 &mut state.kind,
1261 &mut state.output_buf,
1262 &mut state.eof,
1263 )?;
1264 }
1265 FilterKind::RunLengthDecode { .. } => {
1266 let source = state.source;
1267 self.refill_rle(
1268 source,
1269 &mut state.kind,
1270 &mut state.output_buf,
1271 &mut state.eof,
1272 )?;
1273 }
1274 FilterKind::FlateDecode { .. } => {
1275 let source = state.source;
1276 self.refill_flate(
1277 source,
1278 &mut state.kind,
1279 &mut state.output_buf,
1280 &mut state.eof,
1281 )?;
1282 }
1283 FilterKind::LZWDecode { .. } => {
1284 let source = state.source;
1285 self.refill_lzw(
1286 source,
1287 &mut state.kind,
1288 &mut state.output_buf,
1289 &mut state.eof,
1290 )?;
1291 }
1292 FilterKind::DCTDecode { decoded, .. } => {
1293 if !*decoded {
1294 let source = state.source;
1296 let jpeg_data = self.read_all(source)?;
1297 let mut decoder = jpeg_decoder::Decoder::new(jpeg_data.as_slice());
1298 let pixels = decoder
1299 .decode()
1300 .map_err(|e| io::Error::other(format!("JPEG decode error: {e}")))?;
1301 state.output_buf = pixels;
1302 state.output_pos = 0;
1303 *decoded = true;
1304 } else {
1305 state.eof = true;
1306 }
1307 }
1308 FilterKind::CCITTFaxDecode { decoded, .. } => {
1309 if !*decoded {
1310 let source = state.source;
1311 let ccitt_data = self.read_all(source)?;
1312 let decoded_bytes = Self::decode_ccittfax(&ccitt_data, &mut state.kind)?;
1313 state.output_buf = decoded_bytes;
1314 state.output_pos = 0;
1315 if let FilterKind::CCITTFaxDecode { decoded, .. } = &mut state.kind {
1317 *decoded = true;
1318 }
1319 } else {
1320 state.eof = true;
1321 }
1322 }
1323 FilterKind::SubFileDecode { .. } => {
1324 let source = state.source;
1325 self.refill_subfile(
1326 source,
1327 &mut state.kind,
1328 &mut state.output_buf,
1329 &mut state.eof,
1330 )?;
1331 }
1332 FilterKind::EexecDecode { .. } => {
1333 let source = state.source;
1334 self.refill_eexec(
1335 source,
1336 &mut state.kind,
1337 &mut state.output_buf,
1338 &mut state.eof,
1339 )?;
1340 }
1341 _ => {
1343 state.eof = true;
1344 }
1345 }
1346 Ok(())
1347 }
1348
1349 fn refill_ascii_hex(
1351 &mut self,
1352 source: EntityId,
1353 out: &mut Vec<u8>,
1354 eof: &mut bool,
1355 ) -> io::Result<()> {
1356 let mut nibble: Option<u8> = None;
1357 let target = 4096;
1358
1359 while out.len() < target {
1360 match self.read_byte(source)? {
1361 None => {
1362 if let Some(high) = nibble.take() {
1364 out.push(high << 4);
1365 }
1366 *eof = true;
1367 return Ok(());
1368 }
1369 Some(b'>') => {
1370 if let Some(high) = nibble.take() {
1372 out.push(high << 4);
1373 }
1374 *eof = true;
1375 return Ok(());
1376 }
1377 Some(b) => {
1378 let nib = match b {
1379 b'0'..=b'9' => Some(b - b'0'),
1380 b'a'..=b'f' => Some(b - b'a' + 10),
1381 b'A'..=b'F' => Some(b - b'A' + 10),
1382 _ => None, };
1384 if let Some(n) = nib {
1385 match nibble.take() {
1386 None => nibble = Some(n),
1387 Some(high) => out.push((high << 4) | n),
1388 }
1389 }
1390 }
1391 }
1392 }
1393 Ok(())
1394 }
1395
1396 fn refill_ascii85(
1398 &mut self,
1399 source: EntityId,
1400 kind: &mut FilterKind,
1401 out: &mut Vec<u8>,
1402 eof: &mut bool,
1403 ) -> io::Result<()> {
1404 let group = match kind {
1405 FilterKind::ASCII85Decode { group } => group,
1406 _ => return Err(io::Error::other("not ASCII85")),
1407 };
1408 let target = 4096;
1409
1410 while out.len() < target {
1411 match self.read_byte(source)? {
1412 None => {
1413 if group.len() >= 2 {
1415 ascii85_decode_partial(group, out);
1416 }
1417 group.clear();
1418 *eof = true;
1419 return Ok(());
1420 }
1421 Some(b'~') => {
1422 let _ = self.read_byte(source)?; if group.len() >= 2 {
1425 ascii85_decode_partial(group, out);
1426 }
1427 group.clear();
1428 *eof = true;
1429 return Ok(());
1430 }
1431 Some(b'z') => {
1432 out.extend_from_slice(&[0, 0, 0, 0]);
1434 }
1435 Some(b) if b.is_ascii_whitespace() => {
1436 }
1438 Some(b) if (b'!'..=b'u').contains(&b) => {
1439 group.push(b - b'!');
1440 if group.len() == 5 {
1441 let val = group[0] as u64 * 85 * 85 * 85 * 85
1443 + group[1] as u64 * 85 * 85 * 85
1444 + group[2] as u64 * 85 * 85
1445 + group[3] as u64 * 85
1446 + group[4] as u64;
1447 out.push((val >> 24) as u8);
1448 out.push((val >> 16) as u8);
1449 out.push((val >> 8) as u8);
1450 out.push(val as u8);
1451 group.clear();
1452 }
1453 }
1454 Some(_) => {
1455 }
1457 }
1458 }
1459 Ok(())
1460 }
1461
1462 fn refill_rle(
1464 &mut self,
1465 source: EntityId,
1466 kind: &mut FilterKind,
1467 out: &mut Vec<u8>,
1468 eof: &mut bool,
1469 ) -> io::Result<()> {
1470 let rle_state = match kind {
1471 FilterKind::RunLengthDecode { state } => state,
1472 _ => return Err(io::Error::other("not RLE")),
1473 };
1474 let target = 4096;
1475
1476 while out.len() < target {
1477 match rle_state {
1478 RleState::Init => {
1479 match self.read_byte(source)? {
1480 None | Some(128) => {
1481 *rle_state = RleState::Eod;
1482 *eof = true;
1483 return Ok(());
1484 }
1485 Some(b) if b < 128 => {
1486 *rle_state = RleState::Literal {
1487 remaining: b as u16 + 1,
1488 };
1489 }
1490 Some(b) => {
1491 let count = 257 - b as u16;
1493 match self.read_byte(source)? {
1494 None => {
1495 *rle_state = RleState::Eod;
1496 *eof = true;
1497 return Ok(());
1498 }
1499 Some(val) => {
1500 *rle_state = RleState::Repeat {
1501 byte: val,
1502 remaining: count,
1503 };
1504 }
1505 }
1506 }
1507 }
1508 }
1509 RleState::Literal { remaining } => {
1510 if *remaining == 0 {
1511 *rle_state = RleState::Init;
1512 continue;
1513 }
1514 match self.read_byte(source)? {
1515 None => {
1516 *rle_state = RleState::Eod;
1517 *eof = true;
1518 return Ok(());
1519 }
1520 Some(b) => {
1521 out.push(b);
1522 *remaining -= 1;
1523 }
1524 }
1525 }
1526 RleState::Repeat { byte, remaining } => {
1527 if *remaining == 0 {
1528 *rle_state = RleState::Init;
1529 continue;
1530 }
1531 out.push(*byte);
1532 *remaining -= 1;
1533 }
1534 RleState::Eod => {
1535 *eof = true;
1536 return Ok(());
1537 }
1538 }
1539 }
1540 Ok(())
1541 }
1542
1543 fn refill_flate(
1545 &mut self,
1546 source: EntityId,
1547 kind: &mut FilterKind,
1548 out: &mut Vec<u8>,
1549 eof: &mut bool,
1550 ) -> io::Result<()> {
1551 let (decompressor, raw_buf, predictor, columns, colors, bpc, prev_row) = match kind {
1552 FilterKind::FlateDecode {
1553 decompressor,
1554 raw_buf,
1555 predictor,
1556 columns,
1557 colors,
1558 bpc,
1559 prev_row,
1560 } => (
1561 decompressor,
1562 raw_buf,
1563 *predictor,
1564 *columns,
1565 *colors,
1566 *bpc,
1567 prev_row,
1568 ),
1569 _ => return Err(io::Error::other("not Flate")),
1570 };
1571
1572 if raw_buf.is_empty() {
1574 let mut chunk = vec![0u8; 8192];
1575 let mut total = 0;
1576 while let Some(b) = self.read_byte(source)? {
1578 chunk[total] = b;
1579 total += 1;
1580 if total >= chunk.len() {
1581 break;
1582 }
1583 }
1584 if total == 0 {
1585 *eof = true;
1586 return Ok(());
1587 }
1588 raw_buf.extend_from_slice(&chunk[..total]);
1589 }
1590
1591 let mut decompressed = vec![0u8; 16384];
1593 let before_in = decompressor.total_in();
1594 let before_out = decompressor.total_out();
1595 let status = decompressor
1596 .decompress(raw_buf, &mut decompressed, flate2::FlushDecompress::None)
1597 .map_err(|e| io::Error::other(format!("flate2 decompress error: {}", e)))?;
1598
1599 let consumed = (decompressor.total_in() - before_in) as usize;
1600 let produced = (decompressor.total_out() - before_out) as usize;
1601
1602 raw_buf.drain(..consumed);
1604
1605 if status == flate2::Status::StreamEnd {
1606 *eof = true;
1607 }
1608
1609 let decompressed = &decompressed[..produced];
1610
1611 if predictor == 1 || predictor == 0 {
1613 out.extend_from_slice(decompressed);
1615 } else if predictor == 2 {
1616 apply_tiff_predictor(decompressed, out, columns, colors, bpc);
1618 } else if (10..=15).contains(&predictor) {
1619 apply_png_predictor(decompressed, out, columns, colors, bpc, prev_row);
1621 } else {
1622 out.extend_from_slice(decompressed);
1623 }
1624
1625 Ok(())
1626 }
1627
1628 fn refill_lzw(
1630 &mut self,
1631 source: EntityId,
1632 kind: &mut FilterKind,
1633 out: &mut Vec<u8>,
1634 eof: &mut bool,
1635 ) -> io::Result<()> {
1636 let (decoder, raw_buf) = match kind {
1637 FilterKind::LZWDecode { decoder, raw_buf } => (decoder, raw_buf),
1638 _ => return Err(io::Error::other("not LZW")),
1639 };
1640
1641 let mut decompressed = vec![0u8; 16384];
1642
1643 loop {
1644 if raw_buf.is_empty() {
1646 let mut chunk = vec![0u8; 8192];
1647 let mut total = 0;
1648 while let Some(b) = self.read_byte(source)? {
1649 chunk[total] = b;
1650 total += 1;
1651 if total >= chunk.len() {
1652 break;
1653 }
1654 }
1655 if total == 0 {
1656 let result = decoder.decode_bytes(&[], &mut decompressed);
1658 if result.consumed_out > 0 {
1659 out.extend_from_slice(&decompressed[..result.consumed_out]);
1660 }
1661 *eof = true;
1662 return Ok(());
1663 }
1664 raw_buf.extend_from_slice(&chunk[..total]);
1665 }
1666
1667 let result = decoder.decode_bytes(raw_buf, &mut decompressed);
1669 let consumed_in = result.consumed_in;
1670 let consumed_out = result.consumed_out;
1671
1672 raw_buf.drain(..consumed_in);
1674
1675 match result.status {
1676 Ok(weezl::LzwStatus::Done) => {
1677 out.extend_from_slice(&decompressed[..consumed_out]);
1678 *eof = true;
1679 return Ok(());
1680 }
1681 Ok(weezl::LzwStatus::NoProgress) => {
1682 if consumed_out > 0 {
1683 out.extend_from_slice(&decompressed[..consumed_out]);
1684 return Ok(());
1685 }
1686 if raw_buf.is_empty() {
1688 continue; }
1690 *eof = true;
1692 return Ok(());
1693 }
1694 Ok(weezl::LzwStatus::Ok) => {
1695 out.extend_from_slice(&decompressed[..consumed_out]);
1696 if consumed_out > 0 {
1697 return Ok(());
1698 }
1699 continue;
1701 }
1702 Err(e) => {
1703 return Err(io::Error::other(format!("LZW decode error: {}", e)));
1704 }
1705 }
1706 }
1707 }
1708
1709 fn refill_subfile(
1711 &mut self,
1712 source: EntityId,
1713 kind: &mut FilterKind,
1714 out: &mut Vec<u8>,
1715 eof: &mut bool,
1716 ) -> io::Result<()> {
1717 let (eod_string, eod_count, bytes_remaining) = match kind {
1718 FilterKind::SubFileDecode {
1719 eod_string,
1720 eod_count,
1721 bytes_remaining,
1722 } => (eod_string, eod_count, bytes_remaining),
1723 _ => return Err(io::Error::other("not SubFile")),
1724 };
1725
1726 if eod_string.is_empty() {
1727 if let Some(remaining) = bytes_remaining {
1729 let target = (*remaining).min(4096) as usize;
1730 for _ in 0..target {
1731 match self.read_byte(source)? {
1732 Some(b) => {
1733 out.push(b);
1734 *remaining -= 1;
1735 }
1736 None => {
1737 *eof = true;
1738 return Ok(());
1739 }
1740 }
1741 }
1742 if *remaining <= 0 {
1743 *eof = true;
1744 }
1745 } else {
1746 *eof = true;
1747 }
1748 } else {
1749 let eod = eod_string.clone();
1751 let target_count = *eod_count;
1752 let mut match_pos = 0;
1753 let mut found_count = 0;
1754
1755 for _ in 0..4096 {
1756 match self.read_byte(source)? {
1757 None => {
1758 *eof = true;
1759 return Ok(());
1760 }
1761 Some(b) => {
1762 if b == eod[match_pos] {
1763 match_pos += 1;
1764 if match_pos == eod.len() {
1765 found_count += 1;
1766 out.extend_from_slice(&eod);
1768 match_pos = 0;
1769 if found_count >= target_count {
1770 *eof = true;
1771 return Ok(());
1772 }
1773 }
1774 } else {
1775 if match_pos > 0 {
1777 out.extend_from_slice(&eod[..match_pos]);
1778 match_pos = 0;
1779 }
1780 out.push(b);
1781 }
1782 }
1783 }
1784 }
1785 }
1786
1787 Ok(())
1788 }
1789
1790 fn decode_ccittfax(data: &[u8], kind: &mut FilterKind) -> io::Result<Vec<u8>> {
1792 let FilterKind::CCITTFaxDecode {
1793 k,
1794 columns,
1795 rows,
1796 end_of_block,
1797 black_is1,
1798 ..
1799 } = kind
1800 else {
1801 return Err(io::Error::other("not a CCITTFaxDecode filter"));
1802 };
1803 let k = *k;
1804 let width = *columns as u16;
1805 let rows_limit = *rows;
1806 let end_of_block = *end_of_block;
1807 let black_is1 = *black_is1;
1808
1809 let row_bytes = (width as usize).div_ceil(8);
1811 let mut output = Vec::new();
1812 let mut line_count: u32 = 0;
1813
1814 let mut process_line = |transitions: &[u16]| {
1816 if !end_of_block && rows_limit > 0 && line_count >= rows_limit {
1818 return;
1819 }
1820
1821 let line = fax::decoder::Line { transitions, width };
1823 let mut row = vec![0u8; row_bytes];
1824 for (i, color) in line.pels().enumerate() {
1825 if i >= width as usize {
1826 break;
1827 }
1828 let is_set = matches!(color, fax::Color::Black);
1831 if is_set {
1832 row[i / 8] |= 0x80 >> (i % 8);
1833 }
1834 }
1835
1836 if !black_is1 {
1841 for byte in &mut row {
1842 *byte = !*byte;
1843 }
1844 }
1845
1846 output.extend_from_slice(&row);
1847 line_count += 1;
1848 };
1849
1850 if k < 0 {
1851 let height = if rows_limit > 0 {
1853 Some(rows_limit as u16)
1854 } else {
1855 None
1856 };
1857 fax::decoder::decode_g4(data.iter().copied(), width, height, |transitions| {
1858 process_line(transitions)
1859 });
1860 } else {
1861 fax::decoder::decode_g3(data.iter().copied(), |transitions| {
1863 process_line(transitions);
1864 });
1865 }
1866
1867 Ok(output)
1868 }
1869
1870 fn refill_eexec(
1874 &mut self,
1875 source: EntityId,
1876 kind: &mut FilterKind,
1877 out: &mut Vec<u8>,
1878 eof: &mut bool,
1879 ) -> io::Result<()> {
1880 let FilterKind::EexecDecode {
1881 r,
1882 is_hex,
1883 skip_count,
1884 hex_leftover,
1885 } = kind
1886 else {
1887 return Ok(());
1888 };
1889
1890 const C1: u16 = 52845;
1891 const C2: u16 = 22719;
1892 const TARGET: usize = 1;
1897
1898 if is_hex.is_none() {
1900 let mut probe = Vec::with_capacity(8);
1901 for _ in 0..8 {
1902 match self.read_byte(source)? {
1903 Some(b) => probe.push(b),
1904 None => break,
1905 }
1906 }
1907 if probe.is_empty() {
1908 *eof = true;
1909 return Ok(());
1910 }
1911 let hex = probe
1912 .iter()
1913 .all(|&b| b.is_ascii_hexdigit() || is_ps_whitespace(b));
1914 *is_hex = Some(hex);
1915
1916 if hex {
1918 let mut hex_digits = Vec::new();
1919 for &b in &probe {
1920 if b.is_ascii_hexdigit() {
1921 hex_digits.push(b);
1922 }
1923 }
1924 let mut i = 0;
1925 while i + 1 < hex_digits.len() {
1926 let cipher = (hex_val(hex_digits[i]) << 4) | hex_val(hex_digits[i + 1]);
1927 let plain = cipher ^ (*r >> 8) as u8;
1928 *r = (cipher as u16)
1929 .wrapping_add(*r)
1930 .wrapping_mul(C1)
1931 .wrapping_add(C2);
1932 if *skip_count < 4 {
1933 *skip_count += 1;
1934 } else {
1935 out.push(plain);
1936 }
1937 i += 2;
1938 }
1939 if i < hex_digits.len() {
1940 *hex_leftover = Some(hex_digits[i]);
1941 }
1942 } else {
1943 for &cipher in &probe {
1944 let plain = cipher ^ (*r >> 8) as u8;
1945 *r = (cipher as u16)
1946 .wrapping_add(*r)
1947 .wrapping_mul(C1)
1948 .wrapping_add(C2);
1949 if *skip_count < 4 {
1950 *skip_count += 1;
1951 } else {
1952 out.push(plain);
1953 }
1954 }
1955 }
1956 }
1957
1958 while out.len() < TARGET {
1960 let cipher_byte = if *is_hex == Some(true) {
1961 let hi = if let Some(h) = hex_leftover.take() {
1963 h
1964 } else {
1965 match read_next_hex_digit(self, source)? {
1966 Some(d) => d,
1967 None => {
1968 *eof = true;
1969 return Ok(());
1970 }
1971 }
1972 };
1973 let lo = read_next_hex_digit(self, source)?.unwrap_or(b'0');
1975 (hex_val(hi) << 4) | hex_val(lo)
1976 } else {
1977 match self.read_byte(source)? {
1979 Some(b) => b,
1980 None => {
1981 *eof = true;
1982 return Ok(());
1983 }
1984 }
1985 };
1986
1987 let plain = cipher_byte ^ (*r >> 8) as u8;
1988 *r = (cipher_byte as u16)
1989 .wrapping_add(*r)
1990 .wrapping_mul(C1)
1991 .wrapping_add(C2);
1992 if *skip_count < 4 {
1993 *skip_count += 1;
1994 } else {
1995 out.push(plain);
1996 }
1997 }
1998
1999 Ok(())
2000 }
2001}
2002
2003fn read_next_hex_digit(store: &mut FileStore, source: EntityId) -> io::Result<Option<u8>> {
2005 loop {
2006 match store.read_byte(source)? {
2007 Some(b) if b.is_ascii_hexdigit() => return Ok(Some(b)),
2008 Some(b) if is_ps_whitespace(b) => continue,
2009 Some(_) | None => return Ok(None),
2010 }
2011 }
2012}
2013
2014fn is_ps_whitespace(b: u8) -> bool {
2016 matches!(b, b'\0' | b'\t' | b'\n' | 0x0C | b'\r' | b' ')
2017}
2018
2019fn hex_val(b: u8) -> u8 {
2021 match b {
2022 b'0'..=b'9' => b - b'0',
2023 b'a'..=b'f' => b - b'a' + 10,
2024 b'A'..=b'F' => b - b'A' + 10,
2025 _ => 0,
2026 }
2027}
2028
2029fn ascii85_decode_partial(group: &[u8], out: &mut Vec<u8>) {
2031 let n = group.len();
2032 if n < 2 {
2033 return;
2034 }
2035 let mut padded = [84u8; 5];
2037 padded[..n].copy_from_slice(group);
2038
2039 let val = padded[0] as u64 * 85 * 85 * 85 * 85
2040 + padded[1] as u64 * 85 * 85 * 85
2041 + padded[2] as u64 * 85 * 85
2042 + padded[3] as u64 * 85
2043 + padded[4] as u64;
2044
2045 let bytes = [
2046 (val >> 24) as u8,
2047 (val >> 16) as u8,
2048 (val >> 8) as u8,
2049 val as u8,
2050 ];
2051 out.extend_from_slice(&bytes[..n - 1]);
2053}
2054
2055fn flate_compress_data(
2057 compressor: &mut flate2::Compress,
2058 data: &[u8],
2059 mut write_fn: impl FnMut(&[u8]) -> io::Result<()>,
2060) -> io::Result<()> {
2061 let mut out = vec![0u8; data.len() + 64];
2062 let mut input_pos = 0;
2063 loop {
2064 let before_in = compressor.total_in() as usize;
2065 let before_out = compressor.total_out() as usize;
2066 let status = compressor
2067 .compress(&data[input_pos..], &mut out, flate2::FlushCompress::None)
2068 .map_err(|e| io::Error::other(e.to_string()))?;
2069 let consumed = compressor.total_in() as usize - before_in;
2070 let produced = compressor.total_out() as usize - before_out;
2071 input_pos += consumed;
2072 if produced > 0 {
2073 write_fn(&out[..produced])?;
2074 }
2075 if input_pos >= data.len() || matches!(status, flate2::Status::StreamEnd) {
2076 break;
2077 }
2078 }
2079 Ok(())
2080}
2081
2082fn encode_png_row(row: &[u8], bpp: usize) -> Vec<u8> {
2084 let mut encoded = Vec::with_capacity(1 + row.len());
2085 encoded.push(1); for i in 0..row.len() {
2087 let left = if i >= bpp { row[i - bpp] } else { 0 };
2088 encoded.push(row[i].wrapping_sub(left));
2089 }
2090 encoded
2091}
2092
2093fn encode_tiff_row(row: &[u8], colors: usize) -> Vec<u8> {
2095 let mut encoded = Vec::from(row);
2096 for i in (colors..encoded.len()).rev() {
2098 encoded[i] = encoded[i].wrapping_sub(encoded[i - colors]);
2099 }
2100 encoded
2101}
2102
2103fn apply_tiff_predictor(data: &[u8], out: &mut Vec<u8>, columns: u32, colors: u32, bpc: u32) {
2105 let bytes_per_pixel = (colors * bpc).div_ceil(8);
2106 let row_bytes = (columns * colors * bpc).div_ceil(8);
2107
2108 for row in data.chunks(row_bytes as usize) {
2109 let mut prev = vec![0u8; bytes_per_pixel as usize];
2110 for (i, &b) in row.iter().enumerate() {
2111 let pi = i % bytes_per_pixel as usize;
2112 let val = b.wrapping_add(prev[pi]);
2113 out.push(val);
2114 prev[pi] = val;
2115 }
2116 }
2117}
2118
2119fn apply_png_predictor(
2121 data: &[u8],
2122 out: &mut Vec<u8>,
2123 columns: u32,
2124 colors: u32,
2125 bpc: u32,
2126 prev_row: &mut Vec<u8>,
2127) {
2128 let bytes_per_pixel = (colors * bpc).div_ceil(8) as usize;
2129 let row_bytes = (columns * colors * bpc).div_ceil(8) as usize;
2130 let stride = row_bytes + 1; if prev_row.is_empty() {
2133 prev_row.resize(row_bytes, 0);
2134 }
2135
2136 let mut pos = 0;
2137 while pos + stride <= data.len() {
2138 let filter_type = data[pos];
2139 let row_data = &data[pos + 1..pos + stride];
2140 let mut decoded_row = vec![0u8; row_bytes];
2141
2142 for i in 0..row_bytes {
2143 let raw = row_data[i];
2144 let a = if i >= bytes_per_pixel {
2145 decoded_row[i - bytes_per_pixel]
2146 } else {
2147 0
2148 };
2149 let b = prev_row[i];
2150 let c = if i >= bytes_per_pixel {
2151 prev_row[i - bytes_per_pixel]
2152 } else {
2153 0
2154 };
2155
2156 decoded_row[i] = match filter_type {
2157 0 => raw, 1 => raw.wrapping_add(a), 2 => raw.wrapping_add(b), 3 => raw.wrapping_add(((a as u16 + b as u16) / 2) as u8), 4 => raw.wrapping_add(paeth_predictor(a, b, c)), _ => raw,
2163 };
2164 }
2165
2166 out.extend_from_slice(&decoded_row);
2167 prev_row.copy_from_slice(&decoded_row);
2168 pos += stride;
2169 }
2170
2171 if pos < data.len() {
2173 out.extend_from_slice(&data[pos..]);
2174 }
2175}
2176
2177fn paeth_predictor(a: u8, b: u8, c: u8) -> u8 {
2179 let p = a as i32 + b as i32 - c as i32;
2180 let pa = (p - a as i32).abs();
2181 let pb = (p - b as i32).abs();
2182 let pc = (p - c as i32).abs();
2183 if pa <= pb && pa <= pc {
2184 a
2185 } else if pb <= pc {
2186 b
2187 } else {
2188 c
2189 }
2190}
2191
2192impl FilterKind {
2193 pub fn ascii_hex_decode() -> Self {
2195 Self::ASCIIHexDecode
2196 }
2197
2198 pub fn ascii85_decode() -> Self {
2200 Self::ASCII85Decode { group: Vec::new() }
2201 }
2202
2203 pub fn run_length_decode() -> Self {
2205 Self::RunLengthDecode {
2206 state: RleState::Init,
2207 }
2208 }
2209
2210 pub fn flate_decode(predictor: u8, columns: u32, colors: u32, bpc: u32) -> Self {
2212 Self::FlateDecode {
2213 decompressor: flate2::Decompress::new(true),
2214 raw_buf: Vec::new(),
2215 predictor,
2216 columns,
2217 colors,
2218 bpc,
2219 prev_row: Vec::new(),
2220 }
2221 }
2222
2223 pub fn lzw_decode(early_change: bool) -> Self {
2225 let decoder = if early_change {
2226 weezl::decode::Decoder::with_tiff_size_switch(weezl::BitOrder::Msb, 8)
2227 } else {
2228 weezl::decode::Decoder::new(weezl::BitOrder::Msb, 8)
2229 };
2230 Self::LZWDecode {
2231 decoder,
2232 raw_buf: Vec::new(),
2233 }
2234 }
2235
2236 pub fn dct_decode(color_transform: Option<bool>) -> Self {
2238 Self::DCTDecode {
2239 decoded: false,
2240 color_transform,
2241 }
2242 }
2243
2244 pub fn dct_encode(
2246 columns: u32,
2247 rows: u32,
2248 colors: u32,
2249 quality: u8,
2250 color_transform: bool,
2251 ) -> Self {
2252 Self::DCTEncode {
2253 buf: Vec::new(),
2254 columns,
2255 rows,
2256 colors,
2257 quality,
2258 color_transform,
2259 }
2260 }
2261
2262 pub fn sub_file_decode(
2264 eod_string: Vec<u8>,
2265 eod_count: i32,
2266 bytes_remaining: Option<i64>,
2267 ) -> Self {
2268 Self::SubFileDecode {
2269 eod_string,
2270 eod_count,
2271 bytes_remaining,
2272 }
2273 }
2274
2275 pub fn ccittfax_decode(
2277 k: i32,
2278 columns: u32,
2279 rows: u32,
2280 end_of_line: bool,
2281 encoded_byte_align: bool,
2282 end_of_block: bool,
2283 black_is1: bool,
2284 ) -> Self {
2285 Self::CCITTFaxDecode {
2286 decoded: false,
2287 k,
2288 columns,
2289 rows,
2290 end_of_line,
2291 encoded_byte_align,
2292 end_of_block,
2293 black_is1,
2294 }
2295 }
2296
2297 pub fn eexec_decode() -> Self {
2299 Self::EexecDecode {
2300 r: 55665,
2301 is_hex: None,
2302 skip_count: 0,
2303 hex_leftover: None,
2304 }
2305 }
2306
2307 pub fn ascii_hex_encode() -> Self {
2309 Self::ASCIIHexEncode
2310 }
2311
2312 pub fn ascii85_encode() -> Self {
2314 Self::ASCII85Encode {
2315 buf: Vec::with_capacity(4),
2316 col: 0,
2317 }
2318 }
2319
2320 pub fn run_length_encode() -> Self {
2322 Self::RunLengthEncode {
2323 pending: Vec::new(),
2324 run_byte: None,
2325 run_count: 0,
2326 }
2327 }
2328
2329 pub fn flate_encode(predictor: u8, columns: u32, colors: u32, bpc: u32) -> Self {
2331 let row_width = (columns as usize * colors as usize * bpc as usize).div_ceil(8);
2332 let bpp = (colors as usize * bpc as usize).div_ceil(8);
2333 Self::FlateEncode {
2334 compressor: flate2::Compress::new(flate2::Compression::default(), true),
2335 predictor,
2336 columns,
2337 colors,
2338 bpc,
2339 row_width,
2340 bpp: bpp.max(1),
2341 encode_buf: Vec::new(),
2342 prev_row: vec![0u8; row_width],
2343 }
2344 }
2345
2346 pub fn lzw_encode(early_change: bool) -> Self {
2348 let encoder = if early_change {
2349 weezl::encode::Encoder::with_tiff_size_switch(weezl::BitOrder::Msb, 8)
2350 } else {
2351 weezl::encode::Encoder::new(weezl::BitOrder::Msb, 8)
2352 };
2353 Self::LZWEncode { encoder }
2354 }
2355
2356 pub fn null_encode() -> Self {
2358 Self::NullEncode
2359 }
2360
2361 pub fn is_encode(&self) -> bool {
2363 matches!(
2364 self,
2365 Self::ASCIIHexEncode
2366 | Self::ASCII85Encode { .. }
2367 | Self::RunLengthEncode { .. }
2368 | Self::FlateEncode { .. }
2369 | Self::LZWEncode { .. }
2370 | Self::NullEncode
2371 | Self::DCTEncode { .. }
2372 )
2373 }
2374}
2375
2376impl FileStore {
2377 pub fn create_dct_filter(
2379 &mut self,
2380 source: EntityId,
2381 color_transform: Option<bool>,
2382 ) -> EntityId {
2383 self.create_filter(source, FilterKind::dct_decode(color_transform))
2384 }
2385
2386 pub fn create_dct_encode_filter(
2388 &mut self,
2389 target: EntityId,
2390 columns: u32,
2391 rows: u32,
2392 colors: u32,
2393 quality: u8,
2394 color_transform: bool,
2395 ) -> EntityId {
2396 self.create_encode_filter(
2397 target,
2398 FilterKind::dct_encode(columns, rows, colors, quality, color_transform),
2399 )
2400 }
2401}
2402
2403impl Default for FileStore {
2404 fn default() -> Self {
2405 Self::new()
2406 }
2407}
2408
2409#[cfg(test)]
2410mod tests {
2411 use super::*;
2412 use std::io::Write;
2413
2414 fn tmp_path(name: &str) -> String {
2418 std::env::temp_dir()
2419 .join(name)
2420 .to_string_lossy()
2421 .into_owned()
2422 }
2423
2424 #[test]
2425 fn test_prealloc_standard_streams() {
2426 let store = FileStore::new();
2427 assert_eq!(store.len(), 3);
2428 assert!(store.is_open(FILE_STDIN));
2429 assert!(store.is_open(FILE_STDOUT));
2430 assert!(store.is_open(FILE_STDERR));
2431 assert_eq!(store.name(FILE_STDIN), "%stdin");
2432 }
2433
2434 #[test]
2435 fn test_open_special_names() {
2436 let mut store = FileStore::new();
2437 assert_eq!(store.open("%stdin", "r").unwrap(), FILE_STDIN);
2438 assert_eq!(store.open("%stdout", "w").unwrap(), FILE_STDOUT);
2439 assert_eq!(store.open("%stderr", "w").unwrap(), FILE_STDERR);
2440 }
2441
2442 #[test]
2443 fn test_file_round_trip() {
2444 let mut store = FileStore::new();
2445 let path = tmp_path("stet_test_file_store.txt");
2446 let path = path.as_str();
2447
2448 let wid = store.open(path, "w").unwrap();
2450 store.write_from(wid, b"hello\n").unwrap();
2451 store.flush(wid).unwrap();
2452 store.close(wid).unwrap();
2453
2454 let rid = store.open(path, "r").unwrap();
2456 let mut buf = vec![0u8; 6];
2457 let n = store.read_into(rid, &mut buf).unwrap();
2458 assert_eq!(n, 6);
2459 assert_eq!(&buf, b"hello\n");
2460 store.close(rid).unwrap();
2461
2462 std::fs::remove_file(path).ok();
2464 }
2465
2466 #[test]
2467 fn test_readline() {
2468 let mut store = FileStore::new();
2469 let path = tmp_path("stet_test_readline.txt");
2470 let path = path.as_str();
2471
2472 {
2474 let mut f = std::fs::File::create(path).unwrap();
2475 f.write_all(b"line1\nline2\n").unwrap();
2476 }
2477
2478 let id = store.open(path, "r").unwrap();
2479 let mut buf = vec![0u8; 20];
2480 let (n, nl) = store.readline(id, &mut buf).unwrap();
2481 assert_eq!(&buf[..n], b"line1");
2482 assert!(nl);
2483
2484 let (n, nl) = store.readline(id, &mut buf).unwrap();
2485 assert_eq!(&buf[..n], b"line2");
2486 assert!(nl);
2487
2488 store.close(id).unwrap();
2489 std::fs::remove_file(path).ok();
2490 }
2491
2492 #[test]
2493 fn test_file_position() {
2494 let mut store = FileStore::new();
2495 let path = tmp_path("stet_test_filepos.txt");
2496 let path = path.as_str();
2497 {
2498 let mut f = std::fs::File::create(path).unwrap();
2499 f.write_all(b"abcdef").unwrap();
2500 }
2501
2502 let id = store.open(path, "r").unwrap();
2503 assert_eq!(store.position(id).unwrap(), 0);
2504 let mut buf = [0u8; 3];
2505 store.read_into(id, &mut buf).unwrap();
2506 assert_eq!(store.position(id).unwrap(), 3);
2507 store.set_position(id, 0).unwrap();
2508 assert_eq!(store.position(id).unwrap(), 0);
2509 store.close(id).unwrap();
2510 std::fs::remove_file(path).ok();
2511 }
2512
2513 #[test]
2514 fn test_close_and_reopen() {
2515 let mut store = FileStore::new();
2516 let path = tmp_path("stet_test_close.txt");
2517 let path = path.as_str();
2518 let id = store.open(path, "w").unwrap();
2519 store.write_from(id, b"test").unwrap();
2520 store.close(id).unwrap();
2521 assert!(!store.is_open(id));
2522 std::fs::remove_file(path).ok();
2523 }
2524
2525 #[test]
2526 fn test_invalid_mode() {
2527 let mut store = FileStore::new();
2528 assert!(
2529 store
2530 .open(&tmp_path("stet_test_invalid_mode"), "z")
2531 .is_err()
2532 );
2533 }
2534
2535 #[test]
2536 fn test_read_byte() {
2537 let mut store = FileStore::new();
2538 let path = tmp_path("stet_test_readbyte.txt");
2539 let path = path.as_str();
2540 {
2541 let mut f = std::fs::File::create(path).unwrap();
2542 f.write_all(b"AB").unwrap();
2543 }
2544 let id = store.open(path, "r").unwrap();
2545 assert_eq!(store.read_byte(id).unwrap(), Some(b'A'));
2546 assert_eq!(store.read_byte(id).unwrap(), Some(b'B'));
2547 assert_eq!(store.read_byte(id).unwrap(), None);
2548 store.close(id).unwrap();
2549 std::fs::remove_file(path).ok();
2550 }
2551
2552 #[test]
2555 fn test_string_source() {
2556 let mut store = FileStore::new();
2557 let id = store.create_string_source(b"Hello".to_vec());
2558 assert_eq!(store.read_byte(id).unwrap(), Some(b'H'));
2559 assert_eq!(store.read_byte(id).unwrap(), Some(b'e'));
2560 let mut buf = [0u8; 3];
2561 let n = store.read_into(id, &mut buf).unwrap();
2562 assert_eq!(n, 3);
2563 assert_eq!(&buf, b"llo");
2564 assert_eq!(store.read_byte(id).unwrap(), None);
2565 }
2566
2567 #[test]
2568 fn test_string_source_empty() {
2569 let mut store = FileStore::new();
2570 let id = store.create_string_source(Vec::new());
2571 assert_eq!(store.read_byte(id).unwrap(), None);
2572 }
2573
2574 #[test]
2577 fn test_ascii_hex_decode() {
2578 let mut store = FileStore::new();
2579 let src = store.create_string_source(b"48 65 6C 6C 6F>".to_vec());
2580 let filt = store.create_filter(src, FilterKind::ASCIIHexDecode);
2581 let mut result = Vec::new();
2582 loop {
2583 match store.read_byte(filt).unwrap() {
2584 Some(b) => result.push(b),
2585 None => break,
2586 }
2587 }
2588 assert_eq!(&result, b"Hello");
2589 }
2590
2591 #[test]
2592 fn test_ascii_hex_decode_odd_nibble() {
2593 let mut store = FileStore::new();
2594 let src = store.create_string_source(b"4>".to_vec());
2595 let filt = store.create_filter(src, FilterKind::ASCIIHexDecode);
2596 let b = store.read_byte(filt).unwrap().unwrap();
2597 assert_eq!(b, 0x40);
2598 assert_eq!(store.read_byte(filt).unwrap(), None);
2599 }
2600
2601 #[test]
2602 fn test_ascii_hex_decode_whitespace() {
2603 let mut store = FileStore::new();
2604 let src = store.create_string_source(b"4 1\n4 2>".to_vec());
2605 let filt = store.create_filter(src, FilterKind::ASCIIHexDecode);
2606 let mut result = Vec::new();
2607 loop {
2608 match store.read_byte(filt).unwrap() {
2609 Some(b) => result.push(b),
2610 None => break,
2611 }
2612 }
2613 assert_eq!(&result, &[0x41, 0x42]);
2614 }
2615
2616 #[test]
2619 fn test_ascii85_decode() {
2620 let mut store = FileStore::new();
2621 let src = store.create_string_source(b"9jqo^~>".to_vec());
2623 let filt = store.create_filter(src, FilterKind::ASCII85Decode { group: Vec::new() });
2624 let mut result = Vec::new();
2625 loop {
2626 match store.read_byte(filt).unwrap() {
2627 Some(b) => result.push(b),
2628 None => break,
2629 }
2630 }
2631 assert_eq!(&result, b"Man ");
2632 }
2633
2634 #[test]
2635 fn test_ascii85_decode_z() {
2636 let mut store = FileStore::new();
2637 let src = store.create_string_source(b"z~>".to_vec());
2638 let filt = store.create_filter(src, FilterKind::ASCII85Decode { group: Vec::new() });
2639 let mut result = Vec::new();
2640 loop {
2641 match store.read_byte(filt).unwrap() {
2642 Some(b) => result.push(b),
2643 None => break,
2644 }
2645 }
2646 assert_eq!(&result, &[0, 0, 0, 0]);
2647 }
2648
2649 #[test]
2650 fn test_ascii85_decode_partial() {
2651 let mut store = FileStore::new();
2652 let src = store.create_string_source(b"9j~>".to_vec());
2654 let filt = store.create_filter(src, FilterKind::ASCII85Decode { group: Vec::new() });
2655 let mut result = Vec::new();
2656 loop {
2657 match store.read_byte(filt).unwrap() {
2658 Some(b) => result.push(b),
2659 None => break,
2660 }
2661 }
2662 assert_eq!(result.len(), 1);
2663 }
2664
2665 #[test]
2668 fn test_rle_literal() {
2669 let mut store = FileStore::new();
2670 let src = store.create_string_source(vec![2, b'A', b'B', b'C', 128]);
2672 let filt = store.create_filter(
2673 src,
2674 FilterKind::RunLengthDecode {
2675 state: RleState::Init,
2676 },
2677 );
2678 let mut result = Vec::new();
2679 loop {
2680 match store.read_byte(filt).unwrap() {
2681 Some(b) => result.push(b),
2682 None => break,
2683 }
2684 }
2685 assert_eq!(&result, b"ABC");
2686 }
2687
2688 #[test]
2689 fn test_rle_repeat() {
2690 let mut store = FileStore::new();
2691 let src = store.create_string_source(vec![253, b'X', 128]);
2693 let filt = store.create_filter(
2694 src,
2695 FilterKind::RunLengthDecode {
2696 state: RleState::Init,
2697 },
2698 );
2699 let mut result = Vec::new();
2700 loop {
2701 match store.read_byte(filt).unwrap() {
2702 Some(b) => result.push(b),
2703 None => break,
2704 }
2705 }
2706 assert_eq!(&result, b"XXXX");
2707 }
2708
2709 #[test]
2712 fn test_subfile_byte_count() {
2713 let mut store = FileStore::new();
2714 let src = store.create_string_source(b"Hello, World!".to_vec());
2715 let filt = store.create_filter(
2716 src,
2717 FilterKind::SubFileDecode {
2718 eod_string: Vec::new(),
2719 eod_count: 0,
2720 bytes_remaining: Some(5),
2721 },
2722 );
2723 let mut result = Vec::new();
2724 loop {
2725 match store.read_byte(filt).unwrap() {
2726 Some(b) => result.push(b),
2727 None => break,
2728 }
2729 }
2730 assert_eq!(&result, b"Hello");
2731 }
2732
2733 #[test]
2736 fn test_flate_decode() {
2737 use flate2::Compression;
2738 use flate2::write::ZlibEncoder;
2739
2740 let original = b"Hello, stet PostScript interpreter! This is a test of FlateDecode.";
2742 let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default());
2743 encoder.write_all(original).unwrap();
2744 let compressed = encoder.finish().unwrap();
2745
2746 let mut store = FileStore::new();
2747 let src = store.create_string_source(compressed);
2748 let filt = store.create_filter(
2749 src,
2750 FilterKind::FlateDecode {
2751 decompressor: flate2::Decompress::new(true),
2752 raw_buf: Vec::new(),
2753 predictor: 1,
2754 columns: 0,
2755 colors: 0,
2756 bpc: 8,
2757 prev_row: Vec::new(),
2758 },
2759 );
2760 let mut result = Vec::new();
2761 loop {
2762 match store.read_byte(filt).unwrap() {
2763 Some(b) => result.push(b),
2764 None => break,
2765 }
2766 }
2767 assert_eq!(&result, original);
2768 }
2769
2770 #[test]
2773 fn test_lzw_decode() {
2774 let original = b"TOBEORNOTTOBEORTOBEORNOT";
2777 let mut encoder = weezl::encode::Encoder::with_tiff_size_switch(weezl::BitOrder::Msb, 8);
2778 let compressed = encoder.encode(original).unwrap();
2779
2780 let mut store = FileStore::new();
2781 let src = store.create_string_source(compressed);
2782 let filt = store.create_filter(src, FilterKind::lzw_decode(true));
2783 let mut result = Vec::new();
2784 loop {
2785 match store.read_byte(filt).unwrap() {
2786 Some(b) => result.push(b),
2787 None => break,
2788 }
2789 }
2790 assert_eq!(&result, original);
2791 }
2792
2793 #[test]
2794 fn test_lzw_encode_single_byte() {
2795 let mut store = FileStore::new();
2796 let path = tmp_path("stet_test_lzw_single.bin");
2797 let path = path.as_str();
2798
2799 let target = store.open(path, "w").unwrap();
2800 let enc = store.create_encode_filter(target, FilterKind::lzw_encode(true));
2801 store.write_from(enc, b"Q").unwrap();
2802 store.close(enc).unwrap();
2803
2804 let src = store.open(path, "r").unwrap();
2805 let dec = store.create_filter(src, FilterKind::lzw_decode(true));
2806 let mut result = Vec::new();
2807 loop {
2808 match store.read_byte(dec).unwrap() {
2809 Some(b) => result.push(b),
2810 None => break,
2811 }
2812 }
2813 assert_eq!(&result, b"Q");
2814 std::fs::remove_file(path).ok();
2815 }
2816
2817 #[test]
2818 fn test_lzw_encode_roundtrip() {
2819 let mut store = FileStore::new();
2820 let original = b"Hello LZW!";
2821
2822 let path = tmp_path("stet_test_lzw_encode.bin");
2824 let path = path.as_str();
2825 let target = store.open(path, "w").unwrap();
2826 let enc = store.create_encode_filter(target, FilterKind::lzw_encode(true));
2827
2828 store.write_from(enc, original).unwrap();
2830 store.close(enc).unwrap();
2831
2832 let src = store.open(path, "r").unwrap();
2834 let dec = store.create_filter(src, FilterKind::lzw_decode(true));
2835 let mut result = Vec::new();
2836 loop {
2837 match store.read_byte(dec).unwrap() {
2838 Some(b) => result.push(b),
2839 None => break,
2840 }
2841 }
2842 assert_eq!(&result, original);
2843 std::fs::remove_file(path).ok();
2844 }
2845
2846 #[test]
2847 fn test_ascii_hex_encode_roundtrip() {
2848 let mut store = FileStore::new();
2849 let original = b"Hello";
2850 let path = tmp_path("stet_test_hex_encode.bin");
2851 let path = path.as_str();
2852
2853 let target = store.open(path, "w").unwrap();
2854 let enc = store.create_encode_filter(target, FilterKind::ascii_hex_encode());
2855 store.write_from(enc, original).unwrap();
2856 store.close(enc).unwrap();
2857
2858 let src = store.open(path, "r").unwrap();
2859 let dec = store.create_filter(src, FilterKind::ascii_hex_decode());
2860 let mut result = Vec::new();
2861 loop {
2862 match store.read_byte(dec).unwrap() {
2863 Some(b) => result.push(b),
2864 None => break,
2865 }
2866 }
2867 assert_eq!(&result, original);
2868 std::fs::remove_file(path).ok();
2869 }
2870
2871 #[test]
2872 fn test_ascii85_encode_roundtrip() {
2873 let mut store = FileStore::new();
2874 let original = b"Man sure.";
2875 let path = tmp_path("stet_test_a85_encode.bin");
2876 let path = path.as_str();
2877
2878 let target = store.open(path, "w").unwrap();
2879 let enc = store.create_encode_filter(target, FilterKind::ascii85_encode());
2880 store.write_from(enc, original).unwrap();
2881 store.close(enc).unwrap();
2882
2883 let src = store.open(path, "r").unwrap();
2884 let dec = store.create_filter(src, FilterKind::ascii85_decode());
2885 let mut result = Vec::new();
2886 loop {
2887 match store.read_byte(dec).unwrap() {
2888 Some(b) => result.push(b),
2889 None => break,
2890 }
2891 }
2892 assert_eq!(&result, original);
2893 std::fs::remove_file(path).ok();
2894 }
2895
2896 #[test]
2897 fn test_rle_encode_roundtrip() {
2898 let mut store = FileStore::new();
2899 let original = b"AAAAAABCBCBCBC";
2900 let path = tmp_path("stet_test_rle_encode.bin");
2901 let path = path.as_str();
2902
2903 let target = store.open(path, "w").unwrap();
2904 let enc = store.create_encode_filter(target, FilterKind::run_length_encode());
2905 store.write_from(enc, original).unwrap();
2906 store.close(enc).unwrap();
2907
2908 let src = store.open(path, "r").unwrap();
2909 let dec = store.create_filter(src, FilterKind::run_length_decode());
2910 let mut result = Vec::new();
2911 loop {
2912 match store.read_byte(dec).unwrap() {
2913 Some(b) => result.push(b),
2914 None => break,
2915 }
2916 }
2917 assert_eq!(&result, original);
2918 std::fs::remove_file(path).ok();
2919 }
2920
2921 #[test]
2922 fn test_flate_encode_roundtrip() {
2923 let mut store = FileStore::new();
2924 let original = b"Hello Flate compression test data!";
2925 let path = tmp_path("stet_test_flate_encode.bin");
2926 let path = path.as_str();
2927
2928 let target = store.open(path, "w").unwrap();
2929 let enc = store.create_encode_filter(target, FilterKind::flate_encode(1, 1, 1, 8));
2930 store.write_from(enc, original).unwrap();
2931 store.close(enc).unwrap();
2932
2933 let src = store.open(path, "r").unwrap();
2934 let dec = store.create_filter(src, FilterKind::flate_decode(1, 1, 1, 8));
2935 let mut result = Vec::new();
2936 loop {
2937 match store.read_byte(dec).unwrap() {
2938 Some(b) => result.push(b),
2939 None => break,
2940 }
2941 }
2942 assert_eq!(&result, original);
2943 std::fs::remove_file(path).ok();
2944 }
2945}