jmonkeyengine icon indicating copy to clipboard operation
jmonkeyengine copied to clipboard

BinaryExporter resets buffer positions to 0 when writing them.

Open JosiahGoeman opened this issue 1 year ago • 2 comments
trafficstars

When a buffer or buffer arraylist is written using BinaryExporter, the buffer's position gets reset to zero. XMLExporter handles this by restoring the old position after writing. This seems easy enough to fix. It does however bring up another issue currently masked by the position clobbering: shouldn't the position also be serialized? If a buffer with a non-zero position is serialized and the position is preserved, the deserialized buffer will not equals() the original because it will have a zero position. I can easily fix this for XMLExporter with an additional attribute, but from my brief look at BinaryOutputCapsule, it looks like this can't be changed because only one int (length) is expected before the start of the contents.

BinaryExportBufferPositionMRE.java
package com.mygame;

import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
import com.jme3.export.Savable;
import com.jme3.export.binary.BinaryExporter;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import org.lwjgl.BufferUtils;

public class BinaryExportBufferPositionMRE
{
	static class SavableWithBuffer implements Savable
	{
		@Override
		public void write(JmeExporter je) throws IOException
		{
			ByteBuffer bb = BufferUtils.createByteBuffer(16);
			bb.position(4);
			
			OutputCapsule capsule = je.getCapsule(this);
			capsule.write(bb, "buffer", null);
			
			if(bb.position() != 4)
			{
				throw new IOException("Expected buffer position 4, got position: " + bb.position());
			}
		}

		@Override
		public void read(JmeImporter ji) throws IOException
		{
			
		}
	}

	public static void main(String[] args)
	{
		BinaryExporter be = BinaryExporter.getInstance();

		try
		{
			be.save(new SavableWithBuffer(), OutputStream.nullOutputStream());
		} catch(IOException e)
		{
			System.err.println(e);
		}
	}
}

JosiahGoeman avatar Sep 18 '24 09:09 JosiahGoeman

JMonkeyEngine is often selective about which attributes it serializes. Buffer position is ignored in many contexts, so I think it's acceptable to skip serializing it. In contexts where the position is significant, developers can serialize it explicitly.

Similar arguments could be made about serializing a buffer's mark, limit, byte order, and whether it's read-only and/or direct.

It would be good to document (in the javadoc) which attributes of a buffer are automatically serialized.

stephengold avatar Sep 18 '24 18:09 stephengold

Gotcha. I have changed the behavior for XMLExporter to save the position in the referenced PR, so I'll need to revise that.

JosiahGoeman avatar Sep 18 '24 23:09 JosiahGoeman