Open umeat opened 5 years ago
You may need to implement the Packer/Unpacker/BitSizer interfaces for this one, at least until I get back to implementing the expression language features. This would basically amount to manually unpacking. I am at work but I can take a crack at it later today. There’s a bit of documentation in the godoc if you want to try (though it could use improvements.)
After rereading this, it occurred to me that the struct tag would not be accessible. Interesting. I think right now I don't have a good solution for this problem.
With the existence of expressions, I think we’re headed towards a viable solution. What we really need is structs that can be parameterized somehow, and expressions allow that. There’s a couple ways we could go about this:
We could add functionality to just make arbitrary function calls before an underlying struct is decoded/encoded. The pro is that its dead simple, and pretty flexible. The con is that it isn’t very structured.
We could add a new ‘param’ flag for struct fields, and then allow passing params by name. This has the pro that it’s more elegant: we can validate that parameters are passed when necessary, and parameters can be used in expressions automatically. This is probably my preferred method.
Parameterization would be quite useful for me. I have another example from the RTCM parser where it would be useful:
type MsmHeader struct {
MessageNumber uint16 `struct:"uint16:12"`
ReferenceStationId uint16 `struct:"uint16:12"`
Epoch uint32 `struct:"uint32:30"`
MultipleMessageBit bool `struct:"uint8:1,variantbool"`
Iods uint8 `struct:"uint8:3"`
Reserved uint8 `struct:"uint8:7"`
ClockSteeringIndicator uint8 `struct:"uint8:2"`
ExternalClockIndicator uint8 `struct:"uint8:2"`
SmoothingIndicator bool `struct:"uint8:1,variantbool"`
SmoothingInterval uint8 `struct:"uint8:3"`
SatelliteMask uint64 `struct:"uint64"`
SignalMask uint32 `struct:"uint32"`
CellMask uint64 `struct:"bits=bits.OnesCount64(SatelliteMask)*bits.OnesCount32(SignalMask)"`
}
type SatelliteData57 struct {
RangeMilliseconds []uint8 `struct-size:"n"`
Extended []uint8 `struct-size:"n"`
Ranges []uint16 `struct-size:"n"`
PhaseRangeRates []int16 `struct-size:"n"`
}
type SignalData57 struct {
Pseudoranges []int32 `struct-size:"n"`
PhaseRanges []int32 `struct-size:"n"`
PhaseRangeLocks []uint16 `struct-size:"n"`
HalfCycles []bool `struct-size:"n"`
Cnrs []uint16 `struct-size:"n"`
PhaseRangeRates []int16 `struct-size:"n"`
}
type MessageMsm7 struct {
MsmHeader
SatelliteData SatelliteData57 `struct:"param:n=bits.OnesCount64(MsmHeader.SatelliteMask)"`
SignalData SignalData57 `struct:"param:n=bits.OnesCount64(MsmHeader.CellMask)"`
}
Currently I have to do this:
type MsmHeader struct {
MessageNumber uint16 `struct:"uint16:12"`
ReferenceStationId uint16 `struct:"uint16:12"`
Epoch uint32 `struct:"uint32:30"`
MultipleMessageBit bool `struct:"uint8:1,variantbool"`
Iods uint8 `struct:"uint8:3"`
Reserved uint8 `struct:"uint8:7"`
ClockSteeringIndicator uint8 `struct:"uint8:2"`
ExternalClockIndicator uint8 `struct:"uint8:2"`
SmoothingIndicator bool `struct:"uint8:1,variantbool"`
SmoothingInterval uint8 `struct:"uint8:3"`
SatelliteMask uint64 `struct:"uint64"`
SignalMask uint32 `struct:"uint32"`
CellMask uint64 `struct:"bits=bits.OnesCount64(SatelliteMask)*bits.OnesCount32(SignalMask)"`
}
type MessageMsm7 struct {
MsmHeader
RangeMilliseconds []uint8 `struct-size:"bits.OnesCount64(MsmHeader.SatelliteMask)"`
Extended []uint8 `struct-size:"bits.OnesCount64(MsmHeader.SatelliteMask)"`
Ranges []uint16 `struct-size:"bits.OnesCount64(MsmHeader.SatelliteMask)"`
PhaseRangeRates []int16 `struct-size:"bits.OnesCount64(MsmHeader.SatelliteMask)"`
Pseudoranges []int32 `struct-size:"bits.OnesCount64(MsmHeader.CellMask)"`
PhaseRanges []int32 `struct-size:"bits.OnesCount64(MsmHeader.CellMask)"`
PhaseRangeLocks []uint16 `struct-size:"bits.OnesCount64(MsmHeader.CellMask)"`
HalfCycles []bool `struct-size:"bits.OnesCount64(MsmHeader.CellMask)"`
Cnrs []uint16 `struct-size:"bits.OnesCount64(MsmHeader.CellMask)"`
XPhaseRangeRates []int16 `struct-size:"bits.OnesCount64(MsmHeader.CellMask)"`
}
Which is unideal because I can't reuse the Satellite and SignalData structs. Also I have to re-run the same struct-size expression for every field.
I'd like to parse binary sign magnitude integers. Any ideas for how I might implement this?
https://www.ntu.edu.sg/home/ehchua/programming/java/images/DataRep_SignedIntegers.png
I tried making a custom struct type like so:
This is okay, but I want the length of the sint to be variable. Would need to create a separate sint type for every length I need. I'd rather construct a sint from n bits, where sign is first bit and magnitude is n-1 bits long. Something like:
Need a custom type which is capable of representing positive and negative 0. If you convert to int then
Pack(Unpack(data))
would not equaldata
if there is a -0 sint.