Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support varint unpacking #52

Open
abourget opened this issue Mar 9, 2018 · 7 comments
Open

Support varint unpacking #52

abourget opened this issue Mar 9, 2018 · 7 comments

Comments

@abourget
Copy link

abourget commented Mar 9, 2018

I was trying to integrate a varint32 type (like https://github.com/Smerity/govarint/blob/master/govarint.go#L188:6 ..) by adding a type to types.go but I see a Custom declaration needs a Size() which returns a constant..

Do you think it would be easy to modify the lib to support a varint32 type? The size of the read is never defined beforehand.. it could be one byte, two, three, etc..

thanks!

@lunixbochs
Copy link
Owner

lunixbochs commented Mar 9, 2018

The custom Size() method is on an instance of the type, so you'd just need to read the instance value to see what size it is and return that.

Unpack Size() only seems to matter for slices, Custom unpack happens here: https://github.com/lunixbochs/struc/blob/master/fields.go#L150

e.g. https://github.com/lunixbochs/struc/blob/master/custom_float16.go#L73 could read:

func (f *Float16) Size(opt *Options) int {
	if *f < 128 {
		return 1
	} else {
		return 2
	}
}

@abourget
Copy link
Author

abourget commented Mar 9, 2018

but when Size is called, you don't have the data.. so you can't return a variable length.. like a varint would do. Does that make sense ?

@lunixbochs
Copy link
Owner

Size is not called on Unpack. You have the data on Pack. I know exactly how varint works.

@lunixbochs
Copy link
Owner

Seems to work fine for me (note, you shouldn't use Pack to get the size, I just didn't bother looking up the thresholds to hardcode it):

package struc

import (
	"encoding/binary"
	"io"
	"strconv"
)

type ByteWrapper struct {
	io.Reader
}

func (w *ByteWrapper) ReadByte() (byte, error) {
	var b [1]byte
	_, err := w.Read(b[:])
	return b[0], err
}

type Varint uint64

func (v *Varint) Pack(p []byte, opt *Options) (int, error) {
	return binary.PutUvarint(p, uint64(*v)), nil
}
func (v *Varint) Unpack(r io.Reader, length int, opt *Options) error {
	n, err := binary.ReadUvarint(&ByteWrapper{r})
	*v = Varint(n)
	return err
}
func (v *Varint) Size(opt *Options) int {
	var buf [8]byte
	return binary.PutUvarint(buf[:], uint64(*v))
}
func (v *Varint) String() string {
	return strconv.FormatUint(uint64(*v), 10)
}

@abourget
Copy link
Author

Ohh I see.. I'll see if I can take a stab at it. Thanks a lot !

@geoah
Copy link

geoah commented May 21, 2018

@abourget did you by any chance figure out how to integrate varints?

@lunixbochs
Copy link
Owner

Approximately the code I posted should already work in your own codebase without modifying struc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants