use crate::error::{VBError, VBResult};
use crate::state::file;
use crate::state::file::{MAX_FILE_NUMBER, MIN_FILE_NUMBER};
use crate::value::VBVariant;
pub fn line_input(file_number: i16) -> VBResult<VBVariant> {
if !(MIN_FILE_NUMBER..=MAX_FILE_NUMBER).contains(&file_number) {
return Err(VBError::with_description(
52, format!("Bad file name or number: {}", file_number),
));
}
if !file::is_file_open(file_number) {
return Err(VBError::with_description(
52, format!("File not open: #{}", file_number),
));
}
let mut line = String::new();
let mut buf = [0u8; 1];
loop {
let bytes_read = file::read_file(file_number, &mut buf)?;
if bytes_read == 0 {
break;
}
let ch = buf[0] as char;
if ch == '\n' {
break;
} else if ch == '\r' {
let mut next_buf = [0u8; 1];
let next_bytes = file::read_file(file_number, &mut next_buf)?;
if next_bytes > 0 && next_buf[0] as char != '\n' {
}
break;
} else {
line.push(ch);
}
}
Ok(VBVariant::from_string(line))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::state::file::{self, AccessMode, LockMode, OpenMode};
use std::io::Write;
use vb6core::error::err_number;
#[test]
fn line_input_reads_single_line() {
let _guard = crate::state::test_support::lock_test();
let _ = file::close_all_files();
let dir = tempfile::tempdir().unwrap();
file::set_root(dir.path());
let mut test_file = std::fs::File::create(dir.path().join("test.txt")).unwrap();
writeln!(test_file, "First line").unwrap();
writeln!(test_file, "Second line").unwrap();
writeln!(test_file, "Third line").unwrap();
drop(test_file);
let path = std::path::PathBuf::from("test.txt");
file::open_file(
&path,
OpenMode::Input,
AccessMode::Read,
LockMode::Shared,
0,
1,
)
.unwrap();
let line1 = line_input(1).unwrap();
assert_eq!(line1, VBVariant::from_string("First line"));
let line2 = line_input(1).unwrap();
assert_eq!(line2, VBVariant::from_string("Second line"));
let line3 = line_input(1).unwrap();
assert_eq!(line3, VBVariant::from_string("Third line"));
let _ = file::close_all_files();
}
#[test]
fn line_input_handles_empty_lines() {
let _guard = crate::state::test_support::lock_test();
let _ = file::close_all_files();
let dir = tempfile::tempdir().unwrap();
file::set_root(dir.path());
let mut test_file = std::fs::File::create(dir.path().join("test.txt")).unwrap();
writeln!(test_file, "First").unwrap();
writeln!(test_file).unwrap(); writeln!(test_file, "Third").unwrap();
drop(test_file);
let path = std::path::PathBuf::from("test.txt");
file::open_file(
&path,
OpenMode::Input,
AccessMode::Read,
LockMode::Shared,
0,
1,
)
.unwrap();
let line1 = line_input(1).unwrap();
assert_eq!(line1, VBVariant::from_string("First"));
let line2 = line_input(1).unwrap();
assert_eq!(line2, VBVariant::from_string(""));
let line3 = line_input(1).unwrap();
assert_eq!(line3, VBVariant::from_string("Third"));
let _ = file::close_all_files();
}
#[test]
fn line_input_returns_empty_at_eof() {
let _guard = crate::state::test_support::lock_test();
let _ = file::close_all_files();
let dir = tempfile::tempdir().unwrap();
file::set_root(dir.path());
let mut test_file = std::fs::File::create(dir.path().join("test.txt")).unwrap();
write!(test_file, "Only line").unwrap();
drop(test_file);
let path = std::path::PathBuf::from("test.txt");
file::open_file(
&path,
OpenMode::Input,
AccessMode::Read,
LockMode::Shared,
0,
1,
)
.unwrap();
let line1 = line_input(1).unwrap();
assert_eq!(line1, VBVariant::from_string("Only line"));
let line2 = line_input(1).unwrap();
assert_eq!(line2, VBVariant::from_string(""));
let _ = file::close_all_files();
}
#[test]
fn line_input_rejects_invalid_file_number() {
let _guard = crate::state::test_support::lock_test();
let result = line_input(0);
assert!(result.is_err());
assert_eq!(
result.unwrap_err().number,
err_number::BAD_FILE_NAME_OR_NUMBER
);
let _ = file::close_all_files();
}
#[test]
fn line_input_rejects_closed_file() {
let _guard = crate::state::test_support::lock_test();
let _ = file::close_all_files();
let result = line_input(1);
assert!(result.is_err());
assert_eq!(
result.unwrap_err().number,
err_number::BAD_FILE_NAME_OR_NUMBER
);
let _ = file::close_all_files();
}
}