google / flatbuffers

FlatBuffers: Memory Efficient Serialization Library
https://flatbuffers.dev/
Apache License 2.0
23.28k stars 3.25k forks source link

New Java API designe #75

Closed lbensaad closed 9 years ago

lbensaad commented 10 years ago

What do you thing of making the API some thing like the following:

class Main{
     void test(){
        FlatBufferBuilder fbb=new FlatBufferBuilder(256);
        Monster m = new Monster();
        m.startBuilding(fbb);
        int offset=m.addHp((short)20)
                .addMana((short)80)
                .addPos(((Vec3)new Vec3()
                        .startBuilding(fbb))
                        .x(12)
                        .y(12)
                        .z(15)
                        .finishBuilding())
                .finishBuilding();

    }

}
abstract class FlatBuffer {
    protected int bb_pos;
    protected ByteBuffer bb;
    protected FlatBufferBuilder fbb;
    protected int offset;
    public FlatBuffer init (ByteBuffer buffer,int offset) {bb=buffer;bb.order(ByteOrder.LITTLE_ENDIAN);bb_pos = bb.getInt(offset) + offset; return this;}
    public abstract FlatBuffer startBuilding (FlatBufferBuilder fbb);
    public abstract int finishBuilding ();
}    
abstract class Table extends FlatBuffer {
    protected int nField;
    public Table startBuilding (FlatBufferBuilder builder) {fbb=builder;fbb.startObject(nField);offset=fbb.dataStart();return this;}
    public int finishBuilding(){offset=fbb.endObject();return offset;} 

    // here come the other regular __methods()
    protected int __offset(int vtable_offset) {
    int vtable = bb_pos - bb.getInt(bb_pos);
    return vtable_offset < bb.getShort(vtable) ? bb.getShort(vtable + vtable_offset) : 0;
  }
}

abstract class Struct extends FlatBuffer {
    protected int sizeInBytes;
    public Struct startBuilding (FlatBufferBuilder builder) {fbb=builder;fbb.prep(sizeInBytes,0);offset=fbb.dataStart();return this;}
    public int finishBuilding(){return offset;} 
    }

class Monster extends Table{
    public Monster(){nField=15;}

  public Vec3 pos() { return pos(new Vec3()); }
  public Vec3 pos(Vec3 obj) {int o = __offset(4);  return o != 0 ? (Vec3)obj.init(bb,o + bb_pos) : null; }
  public short mana() { int o = __offset(6); return o != 0 ? bb.getShort(o + bb_pos) : 150; }
  public short hp() { int o = __offset(8); return o != 0 ? bb.getShort(o + bb_pos) : 100; }

    // generate only field methods
    public Monster addPos(int posOffset) { fbb.addStruct(0, posOffset, 0); return this;}
    public Monster addMana(short mana) { fbb.addShort(1, mana, 150); return this;}
    public Monster addHp(short hp) { fbb.addShort(2, hp, 100); return this;}
    // and the rest of methods
}

class Vec3 extends Struct {
    public Vec3() {
        sizeInBytes=12;
    }

    public float x() { return bb.getFloat(bb_pos + 0); }
    public float y() { return bb.getFloat(bb_pos + 4); }
    public float z() { return bb.getFloat(bb_pos + 8); }

    public Vec3 x(float x){fbb.dataBuffer().putFloat(offset+0, x); return this;}
    public Vec3 y(float y){fbb.dataBuffer().putFloat(offset+4, y); return this;}
    public Vec3 z(float z){fbb.dataBuffer().putFloat(offset+8, z); return this;}

}
ghost commented 10 years ago

the reason all the addX functions are static is because they don't need an object to function. I'm trying to make the API as efficient as possible by not causing object allocation when none is necessary.

The chaining syntax would not work for all fields, since some already return an offset.

I agree this would be lot nicer though.

lbensaad commented 10 years ago

Yes I agree about efficiency, what about class inheritance model, did you think about it?

ghost commented 10 years ago

I don't see the need for inheritance. In particular, Table's do not need to be dependent on FlatBufferBuilder, you don't need FlatBufferBuilder to read FlatBuffers.