hurl/packages/hurl/src/cli/fs.rs

115 lines
3.3 KiB
Rust

/*
* Hurl (https://hurl.dev)
* Copyright (C) 2023 Orange
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
use std::fs;
use std::fs::File;
use std::io::prelude::*;
use crate::cli::CliError;
/// Remove BOM from the input bytes
fn strip_bom(bytes: &mut Vec<u8>) {
if bytes.starts_with(&[0xefu8, 0xbb, 0xbf]) {
bytes.drain(0..3);
}
}
/// Similar to the standard read_to_string()
/// But remove any existing BOM
/// Support also input stream when filename = '-'
pub fn read_to_string(filename: &str) -> Result<String, CliError> {
if filename == "-" {
let mut contents = String::new();
return if let Err(e) = std::io::stdin().read_to_string(&mut contents) {
Err(CliError {
message: format!("Input stream can not be read - {e}"),
})
} else {
return Ok(contents);
};
}
let mut f = match File::open(filename) {
Ok(f) => f,
Err(e) => {
return Err(CliError {
message: e.to_string(),
})
}
};
let metadata = fs::metadata(filename).expect("unable to read metadata");
let mut buffer = vec![0; metadata.len() as usize];
if let Err(e) = f.read(&mut buffer) {
return Err(CliError {
message: e.to_string(),
});
}
string_from_utf8(buffer)
}
pub fn string_from_utf8(buffer: Vec<u8>) -> Result<String, CliError> {
let mut buffer = buffer;
strip_bom(&mut buffer);
match String::from_utf8(buffer) {
Ok(s) => Ok(s),
Err(e) => Err(CliError {
message: e.to_string(),
}),
}
}
#[cfg(test)]
pub mod tests {
use super::*;
#[test]
fn test_strip_bom() {
let mut bytes = vec![];
strip_bom(&mut bytes);
assert!(bytes.is_empty());
let mut bytes = vec![0xef, 0xbb, 0xbf, 0x68, 0x65, 0x6c, 0x6c, 0x6f];
strip_bom(&mut bytes);
assert_eq!(bytes, vec![0x68, 0x65, 0x6c, 0x6c, 0x6f]);
let mut bytes = vec![0x68, 0x65, 0x6c, 0x6c, 0x6f];
strip_bom(&mut bytes);
assert_eq!(bytes, vec![0x68, 0x65, 0x6c, 0x6c, 0x6f]);
}
#[test]
fn test_string_from_utf8_bom() {
let mut bytes = vec![];
strip_bom(&mut bytes);
assert_eq!(string_from_utf8(vec![]).unwrap(), "");
assert_eq!(
string_from_utf8(vec![0xef, 0xbb, 0xbf, 0x68, 0x65, 0x6c, 0x6c, 0x6f]).unwrap(),
"hello"
);
assert_eq!(
string_from_utf8(vec![0x68, 0x65, 0x6c, 0x6c, 0x6f]).unwrap(),
"hello"
);
assert_eq!(
string_from_utf8(vec![0xef]).err().unwrap(),
CliError {
message: "incomplete utf-8 byte sequence from index 0".to_string()
}
);
}
}