Closed joneshf closed 5 years ago
If your type implements codec.Selfer, that should be sufficient.
See https://godoc.org/github.com/ugorji/go/codec#Selfer
Give it a shot and let me know how it works for you.
Sorry, I'm having a little trouble making it work. For simplicity sake, let's look at just False
and True
:
type Bool struct {
Value bool
}
I've got an interface for expressions:
type Expression interface {
alphaNormalize() Expression
betaNormalize() Expression
}
Is the right way to deal with this by adding the Selfer
interface to the Expression
interface? Like:
type Expression interface {
alphaNormalize() Expression
betaNormalize() Expression
codec.Selfer
}
I've tried this, and I attempt to use it like:
var expression Expression
codec.NewDecoderBytes(in, handle).MustDecode(&expression)
I end up with an error like:
panic: interface conversion: dhall.Expression is not codec.Selfer: missing method CodecDecodeSelf
What did I mess up?
This feels like the most complicated example to use, to illustrate something simple. I'm not even sure how to process the example. So let me just try to write out what the solution should look like.
It's more like this:
type BoolEqual struct {
left bool
right bool
}
func (s *BoolEqual) CodecEncodeSelf(e *Encoder) {
x := []interface{}{3, 2, true, false}
e.MustEncode(x)
}
func (s *testSelferRecur) CodecDecodeSelf(d *Decoder) {
var x = []interface{}{3, 2, false, false}
d.MustDecode(&x)
s.left, s.right = x[2].(bool), x[3].(bool)
}
Something like this. i.e. your type should implement the codec.Selfer interface, and during encoding and decoding, if that type is passed, we will delegate to the implementation you define, instead of using our own heuristics to decode it.
The example is non-trivial because the language is non-trivial. Expressions in Dhall are more than just boolean equality and I'm trying to extrapolate what to do from the simplified example. I can follow the suggestion when there's a single node in the AST:
type BoolEqual struct {
left bool
right bool
}
So the suggestion works for the simplified example, and I thank you for that. However even with just boolean equality, the AST needs to also be non-trivial (as you can say True == False == True
in Dhall, and that cannot be represented with BoolEqual
above). That's the part where I'm stuck, going from the simplified example to the real world.
This is the code I'm working with:
type Expression interface {
alphaNormalize() Expression
}
type BoolValue struct {
value bool
}
func (b *BoolValue) alphaNormalize() Expression { return b }
type BoolEqual struct {
left Expression
right Expression
}
func (b *BoolEqual) alphaNormalize() Expression { return b }
Is there a way to extend this version of the code to use your Selfer
suggestion? If not, is there another way to use this package to make a codec that can? It's fine if this package cannot support this sort of thing.
your type should implement the codec.Selfer interface, and during encoding and decoding, if that type is passed, we will delegate to the implementation you define, instead of using our own heuristics to decode it.
Sorry, this is the issue. There is no one single type to pass at the start of decoding. We get some bytes in over the wire and only once we start decoding can we know what type it's supposed to be. Does this package support this behavior automatically? Or, do you have to manually write that code? I'm fine with either answer, but I don't know what the answer is.
You need to use a io.Reader that allows you to peek at some bytes, so you can peek, and then determine what to decode into.
That's effectively what I'm doing now. Looks like this package doesn't support what I was hoping for. Thanks for the suggestions!
I'm having a bit of trouble understanding if my use case is supported. I'm implementing binary decoding/encoding for Dhall.
The thing that I'm confused about is the encoding of non-trivial expressions. The equality operator, for instance, is encoded as a CBOR array with the first two elements being
3
and2
respectively. E.g., if we wanted to encode the expression:it would be:
Is there a way to represent this transformation using go-codec?
More concretely, if I had this type:
Could I alter it to decode/encode appropriately?