on a736889 help sign in
bat/src/inputfile.rs
135 lines 3.7 kB history raw
1use std::fs::File;
2use std::io::{self, BufRead, BufReader};
4use content_inspector::{self, ContentType};
6use crate::errors::*;
8const THEME_PREVIEW_FILE: &[u8] = include_bytes!("../assets/theme_preview.rs");
10pub struct InputFileReader<'a> {
11 inner: Box<dyn BufRead + 'a>,
12 pub first_line: Vec<u8>,
13 pub content_type: Option<ContentType>,
16impl<'a> InputFileReader<'a> {
17 fn new<R: BufRead + 'a>(mut reader: R) -> InputFileReader<'a> {
18 let mut first_line = vec![];
19 reader.read_until(b'\n', &mut first_line).ok();
21 let content_type = if first_line.is_empty() {
22 None
23 } else {
24 Some(content_inspector::inspect(&first_line[..]))
25 };
27 if content_type == Some(ContentType::UTF_16LE) {
28 reader.read_until(0x00, &mut first_line).ok();
29 }
31 InputFileReader {
32 inner: Box::new(reader),
33 first_line,
34 content_type,
35 }
36 }
38 pub fn read_line(&mut self, buf: &mut Vec<u8>) -> io::Result<bool> {
39 if self.first_line.is_empty() {
40 let res = self.inner.read_until(b'\n', buf).map(|size| size > 0)?;
42 if self.content_type == Some(ContentType::UTF_16LE) {
43 self.inner.read_until(0x00, buf).ok();
44 }
46 Ok(res)
47 } else {
48 buf.append(&mut self.first_line);
49 Ok(true)
50 }
51 }
54#[derive(Debug, Clone, Copy, PartialEq)]
55pub enum InputFile<'a> {
56 StdIn,
57 Ordinary(&'a str),
58 ThemePreviewFile,
61impl<'a> InputFile<'a> {
62 pub fn get_reader(&self, stdin: &'a io::Stdin) -> Result<InputFileReader> {
63 match self {
64 InputFile::StdIn => Ok(InputFileReader::new(stdin.lock())),
65 InputFile::Ordinary(filename) => {
66 let file = File::open(filename).map_err(|e| format!("'{}': {}", filename, e))?;
68 if file.metadata()?.is_dir() {
69 return Err(format!("'{}' is a directory.", filename).into());
70 }
72 Ok(InputFileReader::new(BufReader::new(file)))
73 }
74 InputFile::ThemePreviewFile => Ok(InputFileReader::new(THEME_PREVIEW_FILE)),
75 }
76 }
79#[test]
80fn basic() {
81 let content = b"#!/bin/bash\necho hello";
82 let mut reader = InputFileReader::new(&content[..]);
84 assert_eq!(b"#!/bin/bash\n", &reader.first_line[..]);
86 let mut buffer = vec![];
88 let res = reader.read_line(&mut buffer);
89 assert!(res.is_ok());
90 assert_eq!(true, res.unwrap());
91 assert_eq!(b"#!/bin/bash\n", &buffer[..]);
93 buffer.clear();
95 let res = reader.read_line(&mut buffer);
96 assert!(res.is_ok());
97 assert_eq!(true, res.unwrap());
98 assert_eq!(b"echo hello", &buffer[..]);
100 buffer.clear();
102 let res = reader.read_line(&mut buffer);
103 assert!(res.is_ok());
104 assert_eq!(false, res.unwrap());
105 assert!(buffer.is_empty());
108#[test]
109fn utf16le() {
110 let content = b"\xFF\xFE\x73\x00\x0A\x00\x64\x00";
111 let mut reader = InputFileReader::new(&content[..]);
113 assert_eq!(b"\xFF\xFE\x73\x00\x0A\x00", &reader.first_line[..]);
115 let mut buffer = vec![];
117 let res = reader.read_line(&mut buffer);
118 assert!(res.is_ok());
119 assert_eq!(true, res.unwrap());
120 assert_eq!(b"\xFF\xFE\x73\x00\x0A\x00", &buffer[..]);
122 buffer.clear();
124 let res = reader.read_line(&mut buffer);
125 assert!(res.is_ok());
126 assert_eq!(true, res.unwrap());
127 assert_eq!(b"\x64\x00", &buffer[..]);
129 buffer.clear();
131 let res = reader.read_line(&mut buffer);
132 assert!(res.is_ok());
133 assert_eq!(false, res.unwrap());
134 assert!(buffer.is_empty());