use crate::error::{VBError, VBResult};
use crate::state::file;
use crate::value::VBVariant;
pub fn seek_statement(file_number: VBVariant, position: VBVariant) -> VBResult<()> {
let file_num = match file_number {
VBVariant::Long(v) => v as i16,
VBVariant::Integer(v) => v,
VBVariant::Byte(v) => v as i16,
_ => {
return Err(VBError::with_description(
13, "Type mismatch in Seek statement",
));
}
};
let pos = match position {
VBVariant::Long(v) => v,
VBVariant::Integer(v) => v as i32,
VBVariant::Byte(v) => v as i32,
VBVariant::Double(v) => v as i32,
VBVariant::Single(v) => v as i32,
_ => {
return Err(VBError::with_description(
13, "Type mismatch in Seek statement",
));
}
};
if !(file::MIN_FILE_NUMBER..=file::MAX_FILE_NUMBER).contains(&file_num) {
return Err(VBError::with_description(
52, format!("Bad file name or number: {}", file_num),
));
}
if pos < 1 {
return Err(VBError::with_description(
63, "Bad record number",
));
}
if !file::is_file_open(file_num) {
return Err(VBError::with_description(
52, format!("File not open: #{}", file_num),
));
}
file::seek_file(file_num, pos as i64).map_err(|e| {
VBError::with_description(
57, e.to_string(),
)
})?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::state::file::{self, AccessMode, LockMode, OpenMode};
use vb6core::error::err_number;
#[test]
fn seek_sets_position() {
let _guard = crate::state::test_support::lock_test();
let _ = file::close_all_files();
let dir = tempfile::tempdir().unwrap();
file::set_root(dir.path());
let path = std::path::PathBuf::from("test.txt");
std::fs::write(dir.path().join("test.txt"), "Hello, World!").unwrap();
file::open_file(
&path,
OpenMode::Input,
AccessMode::Read,
LockMode::Shared,
0,
1,
)
.unwrap();
seek_statement(VBVariant::Long(1), VBVariant::Long(7)).unwrap();
let pos = crate::library::file::seek::seek(&VBVariant::Long(1)).unwrap();
assert_eq!(pos.as_i32(), 7);
let _ = file::close_all_files();
}
#[test]
fn seek_rejects_invalid_file_number() {
let _guard = crate::state::test_support::lock_test();
let result = seek_statement(VBVariant::Long(0), VBVariant::Long(1));
assert!(result.is_err());
assert_eq!(
result.unwrap_err().number,
err_number::BAD_FILE_NAME_OR_NUMBER
);
let result = seek_statement(VBVariant::Long(512), VBVariant::Long(1));
assert!(result.is_err());
assert_eq!(
result.unwrap_err().number,
err_number::BAD_FILE_NAME_OR_NUMBER
);
let _ = file::close_all_files();
}
#[test]
fn seek_rejects_invalid_position() {
let _guard = crate::state::test_support::lock_test();
let _ = file::close_all_files();
let dir = tempfile::tempdir().unwrap();
file::set_root(dir.path());
let path = std::path::PathBuf::from("test.txt");
file::open_file(
&path,
OpenMode::Output,
AccessMode::Write,
LockMode::Shared,
0,
1,
)
.unwrap();
let result = seek_statement(VBVariant::Long(1), VBVariant::Long(0));
assert!(result.is_err());
assert_eq!(result.unwrap_err().number, err_number::BAD_RECORD_NUMBER);
let result = seek_statement(VBVariant::Long(1), VBVariant::Long(-1));
assert!(result.is_err());
assert_eq!(result.unwrap_err().number, err_number::BAD_RECORD_NUMBER);
let _ = file::close_all_files();
}
#[test]
fn seek_rejects_closed_file() {
let _guard = crate::state::test_support::lock_test();
let _ = file::close_all_files();
let result = seek_statement(VBVariant::Long(1), VBVariant::Long(1));
assert!(result.is_err());
assert_eq!(
result.unwrap_err().number,
err_number::BAD_FILE_NAME_OR_NUMBER
);
let _ = file::close_all_files();
}
}