trumank / uesave-rs

Rust library to read and write Unreal Engine save files
MIT License
269 stars 53 forks source link

IO Failed to Fill buffer error #1

Closed ntlively closed 1 year ago

ntlively commented 1 year ago

Because you use the same stream for reading and writing, the cursor is moved to the end of the file and any reading will attempt to read there, which will of course fail. You can observe that if you'll print file.stream_position().

You need to rewind() before reading.

Maybe related to most recent update. Only affects 1/3 sav files, other work good

trumank commented 1 year ago

How are you running the tool? I'm not seeing which entry point is re-using a stream.

ntlively commented 1 year ago

2/3 sav files work. the third is different somehow, not sure how. I'm just doing the basic uesave edit ./SaveProfile.susres.sav SaveProfile.susres.sav.md

trumank commented 1 year ago

That save has a MapProperty with 12 byte keys, unlike all other saves I've seen which have 16 bytes (as they are GUIDs). I don't think is any context for the parser to know how many bytes keys are supposed to have so this would require a type hinting system to fix more generally. As a hack to get this save to parse you could do the following:

diff --git a/src/lib.rs b/src/lib.rs
index f3c5faf..6d5a82a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -208,7 +208,7 @@ type UInt32 = u32;
 type Float = f32;
 type Bool = bool;
 type Enum = String;
-type StructKey = uuid::Uuid;
+type StructKey = [u8; 12];

 #[derive(Debug, PartialEq, Serialize, Deserialize)]
 pub struct MapEntry {
@@ -603,14 +603,16 @@ impl ValueKey {
             if id.is_some() {
                 ValueKey::Struct(read_properties_until_none(reader)?)
             } else {
-                ValueKey::StructKey(uuid::Uuid::read(reader)?)
+                let mut id = [0; 12];
+                reader.read_exact(&mut id)?;
+                ValueKey::StructKey(id)
             }
         })
     }
     fn write<W: Write>(&self, writer: &mut W) -> TResult<()> {
         match self {
             ValueKey::Base(v) => v.write(writer)?,
-            ValueKey::StructKey(v) => v.write(writer)?,
+            ValueKey::StructKey(v) => writer.write_all(v)?,
             ValueKey::Struct(v) => write_properties_none_terminated(writer, v)?,
         }
         Ok(())
ntlively commented 1 year ago

Thanks for the information. Not sure why its different, but it is

trumank commented 1 year ago

7c2570f adds type specifications which can be used to parse this save file:

uesave to-json -i SaveProfile.susres.sav.md -t ".SuspendAndResumeData.LevelGenMapData.DoorSpecialCaseSuspendSerializations.Key=Vector"

Note: I don't actually know it's a vector. It's possible it could be another 12 byte struct, but would require some deeper investigation.