From e894f502a45b414ec2407d49b0c75451940d6a5d Mon Sep 17 00:00:00 2001 From: Simon Renblad Date: Wed, 23 Oct 2024 16:02:31 +0800 Subject: [PATCH] fixup read_to_end impl --- libconfig/src/lib.rs | 52 ++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/libconfig/src/lib.rs b/libconfig/src/lib.rs index 667d1d3..82fa194 100644 --- a/libconfig/src/lib.rs +++ b/libconfig/src/lib.rs @@ -1,9 +1,9 @@ #![no_std] extern crate alloc; -use alloc::{rc::Rc, string::FromUtf8Error, string::String, vec::Vec}; +use alloc::{rc::Rc, string::{FromUtf8Error, String}, vec::Vec}; use sd_reader::SdReader; -use core::fmt; +use core::{cmp, fmt}; use fatfs::{self, Read, Seek, SeekFrom, Write}; use libboard_zynq::sdio; @@ -57,23 +57,47 @@ impl<'a> From for Error<'a> { } // Simplified replacements to `read_to_end` and `read_to_string` from core_io -fn read_to_end<'a>(file: &mut File<'a>, buffer: &mut Vec) -> Result<'a, ()> { - let mut temp_buffer = [0; 1024]; - loop { - let read_bytes = file.read(&mut temp_buffer)?; - if read_bytes == 0 { - break; - } - else { - buffer.extend_from_slice(&temp_buffer[..read_bytes]); +fn read_to_end<'a>(file: &mut File<'a>, buffer: &mut Vec) -> Result<'a, usize> { + const PROBE_SIZE: usize = 32; + const MAX_READ_SIZE: usize = 512; // read max BLOCK_SIZE at a time + let start_len = buffer.len(); + let start_cap = buffer.capacity(); + fn small_probe_read<'a>(file: &mut File<'a>, buffer: &mut Vec) -> Result<'a, usize> { + let mut probe = [0u8; PROBE_SIZE]; + let n = file.read(&mut probe)?; + buffer.extend_from_slice(&probe[..n]); + Ok(n) + } + if start_cap - start_len < PROBE_SIZE { + let read = small_probe_read(file, buffer)?; + if read == 0 { + return Ok(0); } } - Ok(()) + loop { + if buffer.len() == buffer.capacity() && buffer.capacity() == start_cap { + let read = small_probe_read(file, buffer)?; + if read == 0 { + return Ok(buffer.len() - start_len); + } + } + if buffer.len() == buffer.capacity() { + buffer.try_reserve(PROBE_SIZE).unwrap(); + } + let mut read_buf = [0u8; MAX_READ_SIZE]; + let buf_len = cmp::min(MAX_READ_SIZE, buffer.capacity() - buffer.len()); + let mut read_buf_mut = &mut read_buf[..buf_len]; + let bytes_read = file.read(&mut read_buf_mut)?; + if bytes_read == 0 { + return Ok(buffer.len() - start_len); + } + buffer.extend_from_slice(&read_buf_mut[..bytes_read]); + } } fn read_to_string<'a>(file: &mut File<'a>) -> Result<'a, String> { let mut buffer: Vec = Vec::new(); - read_to_end(file, &mut buffer)?; + read_to_end(file, &mut buffer).map(|_| ())?; Ok(String::from_utf8(buffer)?) } @@ -128,7 +152,7 @@ impl Config { let root_dir = fs.root_dir(); let mut buffer: Vec = Vec::new(); match root_dir.open_file(&["/CONFIG/", key, ".BIN"].concat()) { - Ok(mut f) => read_to_end( &mut f, &mut buffer)?, + Ok(mut f) => read_to_end( &mut f, &mut buffer).map(|_| ())?, Err(_) => match root_dir.open_file("/CONFIG.TXT") { Ok(f) => parse_config(key, &mut buffer, f)?, Err(_) => return Err(Error::KeyNotFoundError(key)),