Compare commits

...

7 Commits

Author SHA1 Message Date
cw 4d961c1049 WIP: Fix mutability 2020-09-25 15:55:08 +08:00
cw 9066a58d00 WIP: Fix return statement 2020-09-25 15:53:46 +08:00
cw 0f6276e722 WIP: fix borrow 2020-09-22 17:28:30 +08:00
cw e91549d1e8 WIP: fix typos 2020-09-22 17:19:54 +08:00
cw be2869bce5 Add remove and erase methods 2020-09-18 17:30:16 +08:00
cw 822473e8e0 Add blank lines between functions 2020-09-11 16:35:20 +08:00
cw a1564c5218 Add config writing capability
Tested with short (less than 100 characters) and long data strings
2020-09-11 16:30:43 +08:00
1 changed files with 174 additions and 2 deletions

View File

@ -2,8 +2,8 @@
extern crate alloc;
use core::fmt;
use alloc::{string::FromUtf8Error, string::String, vec::Vec, rc::Rc};
use core_io::{self as io, BufRead, BufReader, Read};
use alloc::{string::FromUtf8Error, string::String, vec::Vec, rc::Rc, str};
use core_io::{self as io, BufRead, BufReader, Read, Write, Seek, ErrorKind, SeekFrom};
use libboard_zynq::sdio;
pub mod sd_reader;
@ -67,6 +67,40 @@ fn parse_config<'a>(
Err(Error::KeyNotFoundError(key))
}
fn delete_old_entry<'a>(
key: &str,
file: fatfs::File<sd_reader::SdReader>,
mut file_tmp: fatfs::File<sd_reader::SdReader>,
) -> Result<'a, ()> {
let prefix = [key, "="].concat();
let buf_reader = BufReader::new(file);
for line in buf_reader.lines() {
let line = line?;
if !line.starts_with(&prefix) {
file_tmp.write_all(&[line.as_str(), "\n"].concat().as_bytes())?;
}
}
Ok(())
}
fn rename_file<'a>(dir: &fatfs::Dir<sd_reader::SdReader>, old_file_name: &str, new_file_name: &str) -> Result<'a, ()>{
{
let old_file = dir.open_file(old_file_name)?;
let mut new_file = dir.create_file(new_file_name)?;
new_file.truncate()?;
for line in BufReader::new(old_file).lines() {
let line = line?;
new_file.write_all(&[line.as_str(), "\n"].concat().as_bytes())?;
}
}
dir.remove(old_file_name)?;
Ok(())
}
pub struct Config {
fs: Option<Rc<fatfs::FileSystem<sd_reader::SdReader>>>,
}
@ -112,4 +146,142 @@ impl Config {
pub fn read_str<'b>(&self, key: &'b str) -> Result<'b, String> {
Ok(String::from_utf8(self.read(key)?)?)
}
pub fn erase<'b>(&mut self) -> Result<'b, ()>{
if let Some(fs) = &self.fs {
let root_dir = fs.root_dir();
match root_dir.create_file("/CONFIG.TXT") {
Ok(mut file) => {
file.truncate()?;
},
Err(e) => {
return Err(Error::IoError(e));
}
};
let dir = root_dir.create_dir("/CONFIG")?;
for r in dir.iter() {
let entry = r?;
if entry.is_file() {
dir.remove(str::from_utf8(entry.short_file_name_as_bytes()).unwrap())?;
}
}
Ok(())
} else {
Err(Error::NoConfig)
}
}
pub fn remove_config_txt<'b>(&mut self, key: &str) -> Result<'b, ()>{
if let Some(fs) = &self.fs {
let root_dir = fs.root_dir();
let config_txt_tmp = "/CONFIG.TMP";
let mut need_to_rename = false;
match root_dir.open_file("/CONFIG.TXT") {
Ok(file) => {
need_to_rename = true;
let mut file_tmp = root_dir.create_file(config_txt_tmp)?;
file_tmp.truncate()?;
delete_old_entry(key, file, file_tmp)?;
},
Err(e) => match e.kind() {
ErrorKind::NotFound => {},
_ => {
return Err(Error::IoError(e));
}
}
};
if need_to_rename {
rename_file(&root_dir, config_txt_tmp, "/CONFIG.TXT")?;
}
Ok(())
} else {
Err(Error::NoConfig)
}
}
pub fn remove_config_key_bin<'b>(&mut self, key: &str) -> Result<'b, ()>{
if let Some(fs) = &self.fs {
let root_dir = fs.root_dir();
let config_key_bin = &["/CONFIG/", key, ".BIN"].concat();
match root_dir.remove(config_key_bin) {
Ok(_) => {},
Err(e) => match e.kind() {
ErrorKind::NotFound => {},
_ => {
return Err(Error::IoError(e));
}
}
};
Ok(())
} else {
Err(Error::NoConfig)
}
}
pub fn remove<'b>(&mut self, key: &str) -> Result<'b, ()>{
self.remove_config_txt(key)?;
self.remove_config_key_bin(key)?;
Ok(())
}
pub fn write_str<'b>(&mut self, key: &str, data: &str) -> Result<'b, ()>{
let mut call_remove_config_key_bin = false;
let mut call_remove_config_txt = false;
if let Some(fs) = &self.fs {
let root_dir = fs.root_dir();
let config_key_bin = &["/CONFIG/", key, ".BIN"].concat();
let config_txt_tmp = "/CONFIG.TMP";
if data.is_ascii() & (data.len() <= 100) {
match root_dir.create_file("/CONFIG.TXT") {
Ok(file) => {
let mut file_tmp = root_dir.create_file(config_txt_tmp)?;
file_tmp.truncate()?;
delete_old_entry(key, file, file_tmp)?;
},
Err(e) => {
return Err(Error::IoError(e));
}
};
rename_file(&root_dir, config_txt_tmp, "/CONFIG.TXT")?;
let mut file = root_dir.open_file("/CONFIG.TXT")?;
file.seek(SeekFrom::End(0))?;
file.write_all(&["\n", key, "=", data, "\n"].concat().as_bytes())?;
call_remove_config_key_bin = true;
} else {
root_dir.create_dir("/CONFIG")?;
match root_dir.create_file(config_key_bin) {
Ok(mut file) => {
file.truncate()?;
file.write_all(&[data, "\n"].concat().as_bytes())?;
},
Err(e) => {
return Err(Error::IoError(e));
}
};
call_remove_config_txt = true;
}
} else {
return Err(Error::NoConfig);
}
if call_remove_config_key_bin {
self.remove_config_key_bin(key)?;
}
if call_remove_config_txt {
self.remove_config_txt(key)?;
}
Ok(())
}
}