From a1b5449f06908a26b7d2a67cbbeda843194c845e Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Tue, 4 Apr 2023 12:07:33 +0200 Subject: [PATCH] Some basic tests and basic impls --- schemsearch-cli/src/main.rs | 8 +- schemsearch-cli/src/types.rs | 6 +- schemsearch-faster/src/lib.rs | 16 ++-- schemsearch-files/Cargo.toml | 2 + schemsearch-files/src/lib.rs | 64 ++++++++------- schemsearch-java/src/lib.rs | 6 +- schemsearch-lib/Cargo.toml | 5 +- schemsearch-lib/src/lib.rs | 111 +++++++++++++++++++------- schemsearch-lib/src/pattern_mapper.rs | 24 +++--- 9 files changed, 156 insertions(+), 86 deletions(-) diff --git a/schemsearch-cli/src/main.rs b/schemsearch-cli/src/main.rs index f17f263..fad1b4c 100644 --- a/schemsearch-cli/src/main.rs +++ b/schemsearch-cli/src/main.rs @@ -38,7 +38,7 @@ use schemsearch_sql::load_all_schematics; #[cfg(feature = "sql")] use crate::types::SqlSchematicSupplier; use indicatif::*; -use schemsearch_files::Schematic; +use schemsearch_files::{SchematicVersioned}; use crate::sinks::{OutputFormat, OutputSink}; fn main() { @@ -186,7 +186,7 @@ fn main() { threshold: *matches.get_one::("threshold").expect("Couldn't get threshold"), }; - let pattern = match Schematic::load(&PathBuf::from(matches.get_one::("pattern").unwrap())) { + let pattern = match SchematicVersioned::load(&PathBuf::from(matches.get_one::("pattern").unwrap())) { Ok(x) => x, Err(e) => { cmd.error(ErrorKind::Io, format!("Error while loading Pattern: {}", e.to_string())).exit(); @@ -303,8 +303,8 @@ fn main() { } } -fn load_schem(schem_path: &PathBuf) -> Option { - match Schematic::load(schem_path) { +fn load_schem(schem_path: &PathBuf) -> Option { + match SchematicVersioned::load(schem_path) { Ok(x) => Some(x), Err(e) => { println!("Error while loading schematic ({}): {}", schem_path.to_str().unwrap(), e.to_string()); diff --git a/schemsearch-cli/src/types.rs b/schemsearch-cli/src/types.rs index 5dc7ca5..a6a1d37 100644 --- a/schemsearch-cli/src/types.rs +++ b/schemsearch-cli/src/types.rs @@ -19,7 +19,7 @@ use std::path::PathBuf; #[cfg(feature = "sql")] use futures::executor::block_on; #[allow(unused_imports)] -use schemsearch_files::Schematic; +use schemsearch_files::SpongeV2Schematic; #[cfg(feature = "sql")] use schemsearch_sql::{load_schemdata, SchematicNode}; @@ -46,9 +46,9 @@ pub struct SqlSchematicSupplier { #[cfg(feature = "sql")] impl SqlSchematicSupplier { - pub fn get_schematic(&self) -> Result { + pub fn get_schematic(&self) -> Result { let schemdata = block_on(load_schemdata(self.node.id)); - Schematic::load_data(schemdata.as_slice()) + SchematicVersioned::load_data(schemdata.as_slice()) } pub fn get_name(&self) -> String { diff --git a/schemsearch-faster/src/lib.rs b/schemsearch-faster/src/lib.rs index bc386b0..a6ffa93 100644 --- a/schemsearch-faster/src/lib.rs +++ b/schemsearch-faster/src/lib.rs @@ -16,9 +16,9 @@ */ use nbt::Map; -use schemsearch_files::Schematic; +use schemsearch_files::SpongeV2Schematic; -pub fn convert_to_search_space(schem: &Schematic, palette: &Vec) -> Vec> { +pub fn convert_to_search_space(schem: &SpongeV2Schematic, palette: &Vec) -> Vec> { let mut data: Vec> = Vec::with_capacity(palette.len()); let block_data = &schem.block_data; for name in palette { @@ -48,26 +48,26 @@ pub fn unwrap_palette(palette: &Map) -> Vec { #[cfg(test)] mod tests { use std::path::{Path, PathBuf}; - use schemsearch_files::Schematic; + use schemsearch_files::SpongeV2Schematic; use crate::{convert_to_search_space, unwrap_palette}; //#[test] pub fn test() { - let schematic = Schematic::load(&PathBuf::from("../tests/Pattern.schem")).unwrap(); + let schematic = SpongeV2Schematic::load(&PathBuf::from("../tests/Pattern.schem")).unwrap(); dbg!(convert_to_search_space(&schematic, &unwrap_palette(&schematic.palette))); } //#[test] pub fn test_2() { - let schematic = Schematic::load(&PathBuf::from("../tests/Pattern.schem")).unwrap(); - let schematic2 = Schematic::load(&PathBuf::from("../tests/Random.schem")).unwrap(); + let schematic = SpongeV2Schematic::load(&PathBuf::from("../tests/Pattern.schem")).unwrap(); + let schematic2 = SpongeV2Schematic::load(&PathBuf::from("../tests/Random.schem")).unwrap(); println!("{:?}", convert_to_search_space(&schematic2, &unwrap_palette(&schematic.palette))); } //#[test] pub fn test_big() { - let schematic = Schematic::load(&PathBuf::from("../tests/endstone.schem")).unwrap(); - let schematic2 = Schematic::load(&PathBuf::from("../tests/simple.schem")).unwrap(); + let schematic = SpongeV2Schematic::load(&PathBuf::from("../tests/endstone.schem")).unwrap(); + let schematic2 = SpongeV2Schematic::load(&PathBuf::from("../tests/simple.schem")).unwrap(); let _ = convert_to_search_space(&schematic2, &unwrap_palette(&schematic.palette)); } } \ No newline at end of file diff --git a/schemsearch-files/Cargo.toml b/schemsearch-files/Cargo.toml index 395f9fe..7f53e6d 100644 --- a/schemsearch-files/Cargo.toml +++ b/schemsearch-files/Cargo.toml @@ -6,5 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +flate2 = "1.0.25" hematite-nbt = "0.5.2" serde = "1.0.152" +serde-this-or-that = "0.4.2" diff --git a/schemsearch-files/src/lib.rs b/schemsearch-files/src/lib.rs index b900f74..83c5dc1 100644 --- a/schemsearch-files/src/lib.rs +++ b/schemsearch-files/src/lib.rs @@ -17,34 +17,50 @@ use std::io::Read; use std::path::PathBuf; -use nbt::{Map, Value}; -use serde::{Deserialize, Deserializer, Serialize}; +use nbt::{Error, from_gzip_reader, Map, Value}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use serde_this_or_that::as_i64; #[derive(Serialize, Deserialize, Debug)] -pub struct Schematic { - #[serde(rename = "Version")] +#[serde(untagged)] +pub enum SchematicVersioned { + V1, + V2(SpongeV2Schematic), + V3(SpongeV3Schematic), +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "PascalCase")] +pub struct SpongeV2Schematic { pub version: i32, - #[serde(rename = "DataVersion")] pub data_version: i32, - #[serde(rename = "Metadata")] pub metadata: Map, - #[serde(rename = "Width")] pub width: u16, - #[serde(rename = "Height")] pub height: u16, - #[serde(rename = "Length")] pub length: u16, - #[serde(rename = "Offset")] pub offset: [i32; 3], - #[serde(rename = "PaletteMax")] pub palette_max: i32, - #[serde(rename = "Palette")] pub palette: Map, - #[serde(rename = "BlockData", deserialize_with = "read_blockdata")] + #[serde(deserialize_with = "read_blockdata")] + pub block_data: Vec, + pub block_entities: Vec, + pub entities: Option>, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "PascalCase")] +pub struct SpongeV3Schematic { + pub data_version: i32, + pub metadata: Map, + pub width: u16, + pub height: u16, + pub length: u16, + pub offset: [i32; 3], + pub palette_max: i32, + pub palette: Map, + #[serde(deserialize_with = "read_blockdata")] pub block_data: Vec, - #[serde(rename = "BlockEntities")] pub block_entities: Vec, - #[serde(rename = "Entities")] pub entities: Option>, } @@ -72,21 +88,15 @@ pub struct Entity { pub pos: [i32; 3], } -impl Schematic { - pub fn load_data(data: R) -> Result where R: Read { - let schematic: Schematic = match nbt::from_gzip_reader(data) { - Ok(schem) => schem, - Err(e) => return Err(format!("Failed to parse schematic: {}", e)) - }; +impl SchematicVersioned { + pub fn load_data(data: R) -> Result where R: Read { + let schematic: SchematicVersioned = from_gzip_reader(data)?; Ok(schematic) } - pub fn load(path: &PathBuf) -> Result { - let file = match std::fs::File::open(path) { - Ok(x) => x, - Err(_) => return Err(format!("Failed to open file: {}", path.to_str().unwrap())) - }; - Schematic::load_data(file) + pub fn load(path: &PathBuf) -> Result { + let file = std::fs::File::open(path)?; + Self::load_data(file) } } diff --git a/schemsearch-java/src/lib.rs b/schemsearch-java/src/lib.rs index e9a2d96..35c2b51 100644 --- a/schemsearch-java/src/lib.rs +++ b/schemsearch-java/src/lib.rs @@ -21,7 +21,7 @@ use jni::JNIEnv; use jni::objects::{JClass, JString}; use jni::sys::jstring; -use schemsearch_files::Schematic; +use schemsearch_files::SpongeV2Schematic; use schemsearch_lib::{search, SearchBehavior}; #[no_mangle] @@ -32,8 +32,8 @@ pub extern "system" fn Java_SchemSearch_search<'local>(mut env: JNIEnv<'local>, pattern_path: JString<'local>) -> jstring { let schematic_path: String = env.get_string(&schematic_path).expect("Couldn't get java string!").into(); let pattern_path: String = env.get_string(&pattern_path).expect("Couldn't get java string!").into(); - let schematic = Schematic::load(&PathBuf::from(&schematic_path)).unwrap(); - let pattern = Schematic::load(&PathBuf::from(&pattern_path)).unwrap(); + let schematic = SpongeV2Schematic::load(&PathBuf::from(&schematic_path)).unwrap(); + let pattern = SpongeV2Schematic::load(&PathBuf::from(&pattern_path)).unwrap(); let matches = search(schematic, &pattern, SearchBehavior { ignore_block_data: true, diff --git a/schemsearch-lib/Cargo.toml b/schemsearch-lib/Cargo.toml index 1c340ef..1a7f041 100644 --- a/schemsearch-lib/Cargo.toml +++ b/schemsearch-lib/Cargo.toml @@ -9,4 +9,7 @@ license = "AGPL-3.0-or-later" [dependencies] hematite-nbt = "0.5.2" serde = "1.0.152" -schemsearch-files = { path = "../schemsearch-files" } \ No newline at end of file +schemsearch-files = { path = "../schemsearch-files" } + +[dev-dependencies] +serde_json = "1.0.95" diff --git a/schemsearch-lib/src/lib.rs b/schemsearch-lib/src/lib.rs index c140532..58f1d6f 100644 --- a/schemsearch-lib/src/lib.rs +++ b/schemsearch-lib/src/lib.rs @@ -19,7 +19,8 @@ pub mod pattern_mapper; use serde::{Deserialize, Serialize}; use pattern_mapper::match_palette; -use schemsearch_files::Schematic; +use schemsearch_files::{SchematicVersioned, SpongeV2Schematic}; +use schemsearch_files::SchematicVersioned::V2; use crate::pattern_mapper::match_palette_adapt; #[derive(Debug, Clone, Copy, Deserialize, Serialize)] @@ -33,10 +34,18 @@ pub struct SearchBehavior { } pub fn search( - schem: Schematic, - pattern_schem: &Schematic, + schem: SchematicVersioned, + pattern_schem: &SchematicVersioned, search_behavior: SearchBehavior, ) -> Vec { + let schem = match schem { + V2(x) => x, + _ => return vec![], + }; + let pattern_schem = match pattern_schem { + V2(schem) => schem, + _ => return vec![], + }; if schem.width < pattern_schem.width || schem.height < pattern_schem.height || schem.length < pattern_schem.length { return vec![]; } @@ -132,42 +141,47 @@ pub fn normalize_data(data: &str, ignore_data: bool) -> &str { } } -pub fn parse_schematic(data: &Vec) -> Schematic { - if data[0] == 0x1f && data[1] == 0x8b { - // gzip - nbt::from_gzip_reader(data.as_slice()).unwrap() - } else { - // uncompressed - nbt::from_reader(data.as_slice()).unwrap() - } -} - #[allow(unused_imports)] #[cfg(test)] mod tests { use std::path::{Path, PathBuf}; - use schemsearch_files::Schematic; + use schemsearch_files::SpongeV2Schematic; use crate::pattern_mapper::strip_data; use super::*; #[test] fn read_schematic() { - let schematic = Schematic::load(&PathBuf::from("../tests/simple.schem")).unwrap(); + let schematic = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap(); + + let schematic = match schematic { + V2(schem) => schem, + _ => panic!("Invalid schematic version"), + }; + assert_eq!(schematic.width as usize * schematic.height as usize * schematic.length as usize, schematic.block_data.len()); assert_eq!(schematic.palette_max, schematic.palette.len() as i32); } #[test] fn test_parse_function() { - let file = std::fs::File::open("../tests/simple.schem").expect("Failed to open file"); - let schematic: Schematic = parse_schematic(&std::io::Read::bytes(file).map(|b| b.unwrap()).collect()); + let schematic: SchematicVersioned = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap(); + + let schematic = match schematic { + V2(schem) => schem, + _ => panic!("Invalid schematic version"), + }; + assert_eq!(schematic.width as usize * schematic.height as usize * schematic.length as usize, schematic.block_data.len()); assert_eq!(schematic.palette_max, schematic.palette.len() as i32); } #[test] fn test_strip_schem() { - let schematic = Schematic::load(&PathBuf::from("../tests/simple.schem")).unwrap(); + let schematic = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap(); + let schematic = match schematic { + V2(schem) => schem, + _ => panic!("Invalid schematic version"), + }; let stripped = strip_data(&schematic); assert_eq!(stripped.palette.keys().any(|k| k.contains('[')), false); @@ -175,24 +189,44 @@ mod tests { #[test] fn test_match_palette() { - let schematic = Schematic::load(&PathBuf::from("../tests/simple.schem")).unwrap(); - let endstone = Schematic::load(&PathBuf::from("../tests/endstone.schem")).unwrap(); + let schematic = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap(); + let endstone = SchematicVersioned::load(&PathBuf::from("../tests/endstone.schem")).unwrap(); + + let schematic = match schematic { + V2(schem) => schem, + _ => panic!("Invalid schematic version"), + }; + + let endstone = match endstone { + V2(schem) => schem, + _ => panic!("Invalid schematic version"), + }; let _ = match_palette(&schematic, &endstone, true); } #[test] fn test_match_palette_ignore_data() { - let schematic = Schematic::load(&PathBuf::from("../tests/simple.schem")).unwrap(); - let endstone = Schematic::load(&PathBuf::from("../tests/endstone.schem")).unwrap(); + let schematic = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap(); + let endstone = SchematicVersioned::load(&PathBuf::from("../tests/endstone.schem")).unwrap(); + + let schematic = match schematic { + V2(schem) => schem, + _ => panic!("Invalid schematic version"), + }; + + let endstone = match endstone { + V2(schem) => schem, + _ => panic!("Invalid schematic version"), + }; let _ = match_palette(&schematic, &endstone, false); } #[test] pub fn test_big_search() { - let schematic = Schematic::load(&PathBuf::from("../tests/simple.schem")).unwrap(); - let endstone = Schematic::load(&PathBuf::from("../tests/endstone.schem")).unwrap(); + let schematic = SchematicVersioned::load(&PathBuf::from("../tests/simple.schem")).unwrap(); + let endstone = SchematicVersioned::load(&PathBuf::from("../tests/endstone.schem")).unwrap(); let _ = search(schematic, &endstone, SearchBehavior { ignore_block_data: true, @@ -206,8 +240,8 @@ mod tests { #[test] pub fn test_search() { - let schematic = Schematic::load(&PathBuf::from("../tests/Random.schem")).unwrap(); - let pattern = Schematic::load(&PathBuf::from("../tests/Pattern.schem")).unwrap(); + let schematic = SchematicVersioned::load(&PathBuf::from("../tests/Random.schem")).unwrap(); + let pattern = SchematicVersioned::load(&PathBuf::from("../tests/Pattern.schem")).unwrap(); let matches = search(schematic, &pattern, SearchBehavior { ignore_block_data: true, @@ -228,8 +262,8 @@ mod tests { #[test] pub fn test_search_ws() { - let schematic = Schematic::load(&PathBuf::from("../tests/warships/GreyFly-by-Bosslar.schem")).unwrap(); - let pattern = Schematic::load(&PathBuf::from("../tests/gray_castle_complex.schem")).unwrap(); + let schematic = SchematicVersioned::load(&PathBuf::from("../tests/warships/GreyFly-by-Bosslar.schem")).unwrap(); + let pattern = SchematicVersioned::load(&PathBuf::from("../tests/gray_castle_complex.schem")).unwrap(); let matches = search(schematic, &pattern, SearchBehavior { ignore_block_data: false, @@ -243,4 +277,25 @@ mod tests { println!("{:?}", matches); assert_eq!(matches.len(), 1); } + + #[test] + pub fn sezitest() { + let schem = V2(SpongeV2Schematic { + version: 2, + data_version: 0, + metadata: Default::default(), + width: 0, + height: 0, + length: 0, + offset: [1, 2, 3], + palette_max: 0, + palette: Default::default(), + block_data: vec![], + block_entities: vec![], + entities: None, + }); + + println!("{:?}", schem); + println!("{}", serde_json::to_string_pretty(&schem).unwrap()); + } } diff --git a/schemsearch-lib/src/pattern_mapper.rs b/schemsearch-lib/src/pattern_mapper.rs index edc9632..e56881f 100644 --- a/schemsearch-lib/src/pattern_mapper.rs +++ b/schemsearch-lib/src/pattern_mapper.rs @@ -16,10 +16,10 @@ */ use nbt::Map; -use schemsearch_files::Schematic; +use schemsearch_files::SpongeV2Schematic; use crate::normalize_data; -fn create_reverse_palette(schem: &Schematic) -> Vec<&str> { +fn create_reverse_palette(schem: &SpongeV2Schematic) -> Vec<&str> { let mut reverse_palette = Vec::with_capacity(schem.palette_max as usize); (0..schem.palette_max).for_each(|_| reverse_palette.push("")); for (key, value) in schem.palette.iter() { @@ -28,7 +28,7 @@ fn create_reverse_palette(schem: &Schematic) -> Vec<&str> { reverse_palette } -pub fn strip_data(schem: &Schematic) -> Schematic { +pub fn strip_data(schem: &SpongeV2Schematic) -> SpongeV2Schematic { let mut data: Vec = Vec::new(); let mut palette: Map = Map::new(); @@ -47,7 +47,7 @@ pub fn strip_data(schem: &Schematic) -> Schematic { data.push(*entry); } - Schematic { + SpongeV2Schematic { version: schem.version, data_version: schem.data_version, palette, @@ -63,7 +63,7 @@ pub fn strip_data(schem: &Schematic) -> Schematic { } } -pub fn match_palette_adapt(schem: &Schematic, matching_palette: &Map, ignore_data: bool) -> Vec { +pub fn match_palette_adapt(schem: &SpongeV2Schematic, matching_palette: &Map, ignore_data: bool) -> Vec { let mut data: Vec = Vec::new(); let reverse_palette = create_reverse_palette(schem); @@ -81,10 +81,10 @@ pub fn match_palette_adapt(schem: &Schematic, matching_palette: &Map Schematic { +) -> SpongeV2Schematic { if ignore_data { match_palette_internal(&strip_data(schem), &strip_data(pattern), ignore_data) } else { @@ -93,13 +93,13 @@ pub fn match_palette( } fn match_palette_internal( - schem: &Schematic, - pattern: &Schematic, + schem: &SpongeV2Schematic, + pattern: &SpongeV2Schematic, ignore_data: bool, -) -> Schematic { +) -> SpongeV2Schematic { let data_pattern: Vec = match_palette_adapt(&pattern, &schem.palette, ignore_data); - Schematic { + SpongeV2Schematic { version: pattern.version.clone(), data_version: pattern.data_version.clone(), palette: schem.palette.clone(),