flatbuffers icon indicating copy to clipboard operation
flatbuffers copied to clipboard

[Help Wanted] Bringing LookupByKey functionality to Go

Open Nickersoft opened this issue 3 years ago • 3 comments

Hey FlatBuffer folks!

A little over a year ago I came on here asking about plans to add key searching to the Go generator. I had been meaning to set some time aside to see if I could pick it up, and well... I finally managed to.

I've ported over the core Go methods required in my own branch, and have converted the main lookupByKey method to Go:

func lookupByKey(obj *MyStruct, vector flatbuffers.UOffsetT, k string, buf []byte) bool {
	key := []byte(k)
	span := flatbuffers.GetUOffsetT(buf[vector - 4:])
	start := flatbuffers.UOffsetT(0)
	for ok := true; ok; ok = span != 0 {
		middle := span / 2
		tableOffset := Indirect(vector + 4 * (start + middle), buf)
		comp := Compare(flatbuffers.UOffsetT(Offset(4, flatbuffers.UOffsetT(len(buf)) - tableOffset, buf)), key, buf)
		if comp > 0 {
			span = middle
		} else if comp < 0 {
			middle += 1
			start += middle
			span -= middle
		} else {
			obj.Init(buf, tableOffset)
			return true
		}
	}
	return false
}

And the accessor that uses it:

func (rcv *Dictionary) MyStructByKey(obj *MyStruct, key string) bool {
	o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
	if o != 0 {
		return lookupByKey(obj, rcv._tab.Vector(o), key, rcv._tab.Bytes)
	}
	return false
}

I was able to confirm it working against my own buffers.

Unfortunately, I'm still at a bit of a loss when trying to adapt this to the main generator in idl_gen_go.cpp. Apart from C++ just not being a strong suite of mine, I find the code a bit hard to navigate, and the structure of more recent C++ files (such as the Go and Python) generators are more modularized than older ones which contain code for key lookups (Java, C++, Swift, etc.). So I can't exactly blindly copy and paste between the two haha.

I'm curious if anyone is willing to try to meet me halfway to help get this feature out, or at least offer some guidance regarding how the generators are set up.

Would love to be able to get a PR open for this :)

Nickersoft avatar Aug 20 '22 00:08 Nickersoft

@Nickersoft I can probably help at some point if there are no other offers.

dbaileychess avatar Aug 22 '22 16:08 dbaileychess

That'd be fantastic @dbaileychess! Let me know when/how you'd like to coordinate. I ended up having to make some modifications to the code I posted above, as I wasn't aware of the difference between the various OffsetT types and it turned out my lookup code wouldn't work on large buffers, as it would max out the integer types.

My latest code is here. For now I've just manually extended my generated code in my Go repo.

Nickersoft avatar Aug 23 '22 17:08 Nickersoft

Sorry @Nickersoft didn't see you were working on this.

I have an implementation for this under review in #7644.

le-michael avatar Nov 17 '22 00:11 le-michael

@dbaileychess can we close this?

le-michael avatar Nov 29 '22 21:11 le-michael

I'd say so

Nickersoft avatar Nov 30 '22 07:11 Nickersoft

Hey @le-michael, I just got around to testing the new LookupByKey you added (thanks again btw!) and am getting this error preventing my code from compiling:

image

It looks like the generated file isn't importing the bytes package

Nickersoft avatar Dec 09 '22 10:12 Nickersoft

Hm I was able to reproduce this when using the --gen-onefile flag. Are you using that by any chance?

le-michael avatar Dec 09 '22 15:12 le-michael

I am! So it doesn't happen without the flag? Interesting.. as a workaround right now, I'm just manually adding the bytes import and not regenerating my schema on build.

Nickersoft avatar Dec 10 '22 08:12 Nickersoft

Yeah it's a bug I'll send out a fix for this.

le-michael avatar Dec 10 '22 20:12 le-michael