Clean up the read and write operations

maps no longer need to be serializable. This allows for both a serializable form and a non-serializable form.
This commit is contained in:
Savanni D'Gerinel 2023-01-21 11:23:32 -05:00
parent ac5d8e0c75
commit f17dd5b89d
2 changed files with 44 additions and 40 deletions

View File

@ -10,7 +10,7 @@ Luminescent Dreams Tools is distributed in the hope that it will be useful, but
You should have received a copy of the GNU General Public License along with Luminescent Dreams Tools. If not, see <https://www.gnu.org/licenses/>.
*/
use crate::hex::AxialAddr;
use crate::{hex::AxialAddr, Error};
use nom::{
bytes::complete::tag,
character::complete::alphanumeric1,
@ -29,10 +29,7 @@ pub struct Map<A> {
cells: HashMap<AxialAddr, A>,
}
impl<A: Default + From<String> + Clone> Map<A>
where
String: From<A>,
{
impl<A: Default + Clone> Map<A> {
pub fn new_hexagonal(radius: usize) -> Map<A> {
let cells = vec![(AxialAddr::origin(), Default::default())]
.into_iter()
@ -56,40 +53,46 @@ where
pub fn get(&self, addr: &AxialAddr) -> Option<&A> {
self.cells.get(addr)
}
}
// pub fn from_file(path: PathBuf) -> Map<A> {}
pub fn read_file<A: Default + From<String>>(path: PathBuf) -> Result<Map<A>, Error> {
let data = std::fs::read_to_string(path)?;
Ok(parse_data(data.lines()))
}
pub fn to_file(&self, path: PathBuf) -> () {}
pub fn write_file<A: Clone>(path: PathBuf, map: Map<A>) -> Result<(), Error>
where
String: From<A>,
{
std::fs::write(path, write_data(map).join("\n")).map_err(Error::from)
}
pub fn from_data(data: Vec<String>) -> Map<A> {
fn parse_line<A: From<String>>(
input: &str,
) -> Result<(AxialAddr, A), nom::error::Error<&str>> {
fn parse<A: From<String>>(input: &str) -> IResult<&str, (AxialAddr, A)> {
let (input, addr) = parse_address(input)?;
let (input, value) = cell_value::<A>(input)?;
Ok((input, (addr, value)))
}
parse(input).finish().map(|(_, pair)| pair)
fn parse_data<'a, A: Default + From<String>>(data: impl Iterator<Item = &'a str> + 'a) -> Map<A> {
fn parse_line<A: From<String>>(input: &str) -> Result<(AxialAddr, A), nom::error::Error<&str>> {
fn parse<A: From<String>>(input: &str) -> IResult<&str, (AxialAddr, A)> {
let (input, addr) = parse_address(input)?;
let (input, value) = cell_value::<A>(input)?;
Ok((input, (addr, value)))
}
let cells = data
.into_iter()
.map(|line| parse_line::<A>(&line).unwrap())
.collect::<Vec<(AxialAddr, A)>>();
let cells = cells.into_iter().collect::<HashMap<AxialAddr, A>>();
Map { cells }
parse(input).finish().map(|(_, pair)| pair)
}
pub fn to_data(&self) -> Vec<String> {
self.cells
.iter()
.map(|(addr, val)| {
format!("[{}, {}] {}", addr.q(), addr.r(), String::from(val.clone()))
})
.collect()
}
let cells = data
.map(|line| parse_line::<A>(&line).unwrap())
.collect::<Vec<(AxialAddr, A)>>();
let cells = cells.into_iter().collect::<HashMap<AxialAddr, A>>();
Map { cells }
}
fn write_data<A: Clone>(map: Map<A>) -> Vec<String>
where
String: From<A>,
{
map.cells
.iter()
.map(|(addr, val)| format!("[{}, {}] {}", addr.q(), addr.r(), String::from(val.clone())))
.collect()
}
fn parse_address(input: &str) -> IResult<&str, AxialAddr> {
@ -163,7 +166,7 @@ mod test {
expected.insert("[0, -1] .".to_owned());
expected.insert("[1, -1] .".to_owned());
let map_rows = map.to_data();
let map_rows = write_data(map);
assert_eq!(map_rows.len(), expected.len());
map_rows
.iter()
@ -182,12 +185,7 @@ mod test {
[-1, 0] .
[0, -1] .
[1, -1] .";
let map: Map<MapVal> = Map::from_data(
map_data
.lines()
.map(|l| l.to_owned())
.collect::<Vec<String>>(),
);
let map: Map<MapVal> = parse_data(map_data.lines());
assert_eq!(map.get(&AxialAddr::new(0, 0)), Some(&MapVal('L')));
assert_eq!(map.get(&AxialAddr::new(1, 0)), Some(&MapVal('A')));
assert_eq!(map.get(&AxialAddr::new(0, 1)), Some(&MapVal('.')));

View File

@ -17,7 +17,13 @@ pub enum Error {
IO(std::io::Error),
}
impl From<std::io::Error> for Error {
fn from(err: std::io::Error) -> Self {
Self::IO(err)
}
}
mod hex;
mod hex_map;
pub mod hex_map;
pub use hex::AxialAddr;