use crate::io::error::{IoError, IoResult};
use std::io::{BufRead, BufReader, Write};
use crate::mock_types::MockTrainingData;
pub struct TrainingDataReader {
}
impl TrainingDataReader {
pub fn new() -> Self {
Self {}
}
pub fn read_data<R: std::io::Read>(&self, reader: &mut R) -> IoResult<MockTrainingData> {
let mut buf_reader = BufReader::new(reader);
let mut line = String::new();
buf_reader.read_line(&mut line)?;
let header_parts: Vec<&str> = line.split_whitespace().collect();
if header_parts.len() != 3 {
return Err(IoError::InvalidFileFormat(
"Header must contain exactly 3 numbers: num_data num_input num_output".to_string(),
));
}
let num_data: usize = header_parts[0]
.parse()
.map_err(|e| IoError::ParseError(format!("Invalid num_data: {e}")))?;
let num_input: usize = header_parts[1]
.parse()
.map_err(|e| IoError::ParseError(format!("Invalid num_input: {e}")))?;
let num_output: usize = header_parts[2]
.parse()
.map_err(|e| IoError::ParseError(format!("Invalid num_output: {e}")))?;
let mut inputs = Vec::with_capacity(num_data);
let mut outputs = Vec::with_capacity(num_data);
for i in 0..num_data {
line.clear();
buf_reader.read_line(&mut line)?;
let input_values: Result<Vec<f32>, _> =
line.split_whitespace().map(|s| s.parse()).collect();
let input_values = input_values
.map_err(|e| IoError::ParseError(format!("Invalid input at sample {i}: {e}")))?;
if input_values.len() != num_input {
return Err(IoError::InvalidTrainingData(format!(
"Expected {} inputs at sample {}, got {}",
num_input,
i,
input_values.len()
)));
}
line.clear();
buf_reader.read_line(&mut line)?;
let output_values: Result<Vec<f32>, _> =
line.split_whitespace().map(|s| s.parse()).collect();
let output_values = output_values
.map_err(|e| IoError::ParseError(format!("Invalid output at sample {i}: {e}")))?;
if output_values.len() != num_output {
return Err(IoError::InvalidTrainingData(format!(
"Expected {} outputs at sample {}, got {}",
num_output,
i,
output_values.len()
)));
}
inputs.push(input_values);
outputs.push(output_values);
}
Ok(MockTrainingData {
num_data,
num_input,
num_output,
inputs,
outputs,
})
}
}
impl Default for TrainingDataReader {
fn default() -> Self {
Self::new()
}
}
pub struct TrainingDataWriter {
}
impl TrainingDataWriter {
pub fn new() -> Self {
Self {}
}
pub fn write_data<W: Write>(&self, data: &MockTrainingData, writer: &mut W) -> IoResult<()> {
writeln!(
writer,
"{} {} {}",
data.num_data, data.num_input, data.num_output
)?;
for i in 0..data.num_data {
for (j, &input) in data.inputs[i].iter().enumerate() {
if j > 0 {
write!(writer, " ")?;
}
if input.fract() == 0.0 && input.abs() < 1e6 {
write!(writer, "{}", input as i32)?;
} else {
write!(writer, "{input}")?;
}
}
writeln!(writer)?;
for (j, &output) in data.outputs[i].iter().enumerate() {
if j > 0 {
write!(writer, " ")?;
}
if output.fract() == 0.0 && output.abs() < 1e6 {
write!(writer, "{}", output as i32)?;
} else {
write!(writer, "{output}")?;
}
}
writeln!(writer)?;
}
Ok(())
}
}
impl Default for TrainingDataWriter {
fn default() -> Self {
Self::new()
}
}
pub struct TrainingDataStreamReader {
}
impl TrainingDataStreamReader {
pub fn new() -> Self {
Self {}
}
pub fn read_stream<R, F>(&self, reader: &mut R, mut callback: F) -> IoResult<()>
where
R: BufRead,
F: FnMut(&[f32], &[f32]) -> IoResult<()>,
{
let mut line = String::new();
reader.read_line(&mut line)?;
let header_parts: Vec<&str> = line.split_whitespace().collect();
if header_parts.len() != 3 {
return Err(IoError::InvalidFileFormat(
"Header must contain exactly 3 numbers: num_data num_input num_output".to_string(),
));
}
let num_data: usize = header_parts[0].parse()?;
let num_input: usize = header_parts[1].parse()?;
let num_output: usize = header_parts[2].parse()?;
for i in 0..num_data {
line.clear();
reader.read_line(&mut line)?;
let input_values: Result<Vec<f32>, _> =
line.split_whitespace().map(|s| s.parse()).collect();
let input_values = input_values
.map_err(|e| IoError::ParseError(format!("Invalid input at sample {i}: {e}")))?;
if input_values.len() != num_input {
return Err(IoError::InvalidTrainingData(format!(
"Expected {} inputs at sample {}, got {}",
num_input,
i,
input_values.len()
)));
}
line.clear();
reader.read_line(&mut line)?;
let output_values: Result<Vec<f32>, _> =
line.split_whitespace().map(|s| s.parse()).collect();
let output_values = output_values
.map_err(|e| IoError::ParseError(format!("Invalid output at sample {i}: {e}")))?;
if output_values.len() != num_output {
return Err(IoError::InvalidTrainingData(format!(
"Expected {} outputs at sample {}, got {}",
num_output,
i,
output_values.len()
)));
}
callback(&input_values, &output_values)?;
}
Ok(())
}
}
impl Default for TrainingDataStreamReader {
fn default() -> Self {
Self::new()
}
}