Itch: Parse paths as lossy

This commit is contained in:
Philip Kristoffersen
2022-03-10 07:04:58 +01:00
parent c188c6f385
commit dbe7abdcbc
3 changed files with 27 additions and 29 deletions
+24 -25
View File
@@ -5,41 +5,29 @@ use nom::{
}; };
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub(crate) struct DbPaths<'a> { pub(crate) struct DbPaths {
pub(crate) base_path: &'a str, pub(crate) base_path: String,
pub(crate) path: &'a str, pub(crate) path: String,
} }
pub(crate) fn parse_butler_db<'a>(content: &'a [u8]) -> nom::IResult<&[u8], Vec<DbPaths<'a>>> { pub(crate) fn parse_butler_db<'a>(content: &'a [u8]) -> nom::IResult<&[u8], Vec<DbPaths>> {
many0(parse_path)(content) many0(parse_path)(content)
} }
fn parse_path<'a>(i: &'a [u8]) -> nom::IResult<&[u8], DbPaths<'a>> { fn parse_path<'a>(i: &'a [u8]) -> nom::IResult<&[u8], DbPaths> {
let prefix = "{\"basePath\":\""; let prefix = "{\"basePath\":\"";
let suffix = "\",\"totalSize\""; let suffix = "\",\"totalSize\"";
let (i, _taken) = take_until(prefix)(i)?; let (i, _taken) = take_until(prefix)(i)?;
let (i, _taken) = tag(prefix)(i)?; let (i, _taken) = tag(prefix)(i)?;
let (i, base_path) = take_until(suffix)(i)?; let (i, base_path) = take_until(suffix)(i)?;
let base_path_str = std::str::from_utf8(base_path); let base_path = String::from_utf8_lossy(base_path).to_string();
let base_path = match base_path_str{
Ok(base_path) => base_path,
Err(e) => {
return convert_to_nom_error(i, e);
},
};
let prefix = ":[{\"path\":\""; let prefix = ":[{\"path\":\"";
let suffix = "\",\"depth"; let suffix = "\",\"depth";
let (i, _taken) = take_until(prefix)(i)?; let (i, _taken) = take_until(prefix)(i)?;
let (i, _taken) = tag(prefix)(i)?; let (i, _taken) = tag(prefix)(i)?;
let (i, path) = take_until(suffix)(i)?; let (i, path) = take_until(suffix)(i)?;
let path_str = std::str::from_utf8(path); let path = String::from_utf8_lossy(path).to_string();
let path = match path_str{
Ok(path) => path,
Err(e) => {
return convert_to_nom_error(i, e);
},
};
IResult::Ok(( IResult::Ok((
i, i,
@@ -50,12 +38,6 @@ fn parse_path<'a>(i: &'a [u8]) -> nom::IResult<&[u8], DbPaths<'a>> {
)) ))
} }
fn convert_to_nom_error(i: &[u8], e: std::str::Utf8Error) -> Result<(&[u8], DbPaths), nom::Err<nom::error::Error<&[u8]>>> {
use nom::error::*;
IResult::Err(nom::Err::Error(Error::from_external_error(i, ErrorKind::AlphaNumeric,e)))
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
@@ -91,4 +73,21 @@ mod tests {
assert_eq!(paths[5].base_path, "/home/philip/.config/itch/apps/islands"); assert_eq!(paths[5].base_path, "/home/philip/.config/itch/apps/islands");
assert_eq!(paths[5].path, "Islands_Linux.x86_64"); assert_eq!(paths[5].path, "Islands_Linux.x86_64");
} }
#[test]
fn parse_itch_butler_db_test_other() {
let content = include_bytes!("../testdata/itch/other-butler.db-wal");
let result = parse_butler_db(content);
assert!(result.is_ok());
let (_r, paths) = result.unwrap();
assert_eq!(paths.len(), 94);
assert_eq!(paths[0].base_path, "/home/deck/.config/itch/apps/risetoruins");
assert_eq!(paths[0].path, "Core.jar");
//The parser finds douplicates
assert_eq!(paths[0], paths[1]);
assert_eq!(paths[1], paths[2]);
}
} }
+3 -4
View File
@@ -48,9 +48,8 @@ impl Platform<ItchGame, ItchErrors> for ItchPlatform {
}), }),
}?; }?;
//This is done to remove douplicates //This is done dedupe
let paths: HashSet<&DbPaths> = paths.iter().collect(); let paths: HashSet<&DbPaths> = paths.iter().collect();
let res = paths.iter().filter_map(|e| dbpath_to_game(*e)).collect(); let res = paths.iter().filter_map(|e| dbpath_to_game(*e)).collect();
Ok(res) Ok(res)
} }
@@ -71,8 +70,8 @@ impl Platform<ItchGame, ItchErrors> for ItchPlatform {
} }
} }
fn dbpath_to_game(paths: &DbPaths<'_>) -> Option<ItchGame> { fn dbpath_to_game(paths: &DbPaths) -> Option<ItchGame> {
let recipt = Path::new(paths.base_path) let recipt = Path::new(paths.base_path.as_str())
.join(".itch") .join(".itch")
.join("receipt.json.gz"); .join("receipt.json.gz");
if !&recipt.exists() { if !&recipt.exists() {
Binary file not shown.