La estructura Data contiene toda la información que podrÃa generar un sensor base.
Se necesita construir lo siguiente.
Todo está definido bajo una estrucura de directorios.
tree src
Es la serie de funciones que construyen aleatoriamente datos a solicitud.
En generators.rs tenemos la función createdata que genera una instancia de Data aleatoria.
Creación de comando que permite una entrada y deserializarla. Sea un stream o de un archivo.
Hay dos funciones sÃncronas que permite leer o escribir desde un stream.
De estas dos derivan las asociadas a archivos, para leer o escribir a archivos.
AsÃmismo, de manera asÃncrona se usa tokio para crear las funciones que toman leen desde un buffer y lo envÃan por un canal y viceversa.
Estas funcionalidades son claves para que este módulo se pueda utilizar, por ejemplo, en servidores tcp o servicios generadores de datos para simular sensores.
En stream.rs -> readfile se implementa una función sencilla que toma un archivo completo y lo deserializa directamente para convertirlo en un array de Data.
Esto es solo para un archivo de tipo json.
pub fn read_file<P: AsRef<Path>>(
path: P) -> Result<Vec<Data>, Box<dyn Error>> {
// open file if exists path
let file = File::open(path)?;
// set file to buffer
let reader = BufReader::new(file);
// read the json contents
let json_data = serde_json::from_reader(reader)?;
// Return Data
Ok(json_data)
}
Si el origen del dato viene de un stream, entonces se usa readio que toma la serie de valores (o de un archivo no json)
pub fn read_io<R: io::BufRead >(
mut input: R,
end_flag: &String,
print: bool) -> Result<Vec<Data>, Box<dyn Error>> {
let mut lines: Vec<String> = vec![];
let mut dataset: Vec<Data> = vec![];
for value in input.lines() {
let line = value?;
if line.as_str().trim() == end_flag {
let new_value = lines.join("");
let new_data = Data::json_loads(&new_value);
if print {
println!("{}", new_data);
}
dataset.push(new_data);
lines.clear();
} else {
if !line.trim().is_empty() {
lines.push(line);
}
}
}
Ok(dataset)
}
En este caso, en vez de lograr un acumulador, tomar el Data convertido enviarlo mediante un stream con rasgo Write.
Por ejemplo, podrÃa necesitar enviarlo por una cola a un stream de socket, entonces crear un módulo que tome el dato, lo procese y envÃe a otra parte, si es que lo necesita. También podrÃa utilizarse para enviar a un proceso concurrente o funcionalidad atómica separada.
Todas las operaciones disponibles para crear datos y enviarlos o recibirlos por stream están testeadas.
Revisar los tests pueden servir para aprender a usar las funciones.