Skip to content

Commit

Permalink
workaround Go generic limitations
Browse files Browse the repository at this point in the history
  • Loading branch information
pascaldekloe committed Jul 2, 2024
1 parent 7b37abd commit 8c94f8e
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 22 deletions.
41 changes: 21 additions & 20 deletions info/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/binary"
"errors"
"math"
"unsafe"
)

// Information Object Address
Expand All @@ -15,47 +16,47 @@ type (

// N gets the address as a numeric value.
N() uint

// SetN updates the address as a numeric value.
SetN(uint)
}

Addr8 [1]uint8
Addr16 [2]uint8
Addr24 [3]uint8
)

// NewAddrN returns a numeric address mapping. The return is false
// when the numeric value does not fit the width of address type T.
func NewAddrN[T Addr](n uint) (T, bool) {
var addr T

// addr[0] = uint8(n)
// Go's generics suck. Can't slice the type either.
// https://github.com/golang/go/issues/44253

view := unsafe.Slice(&addr[0], len(addr))
for i := range view {
view[i] = uint8(n)
n <<= 8
}

return addr, n == 0
}

// N implements the Addr interface.
func (addr Addr8) N() uint { return uint(addr[0]) }

// SetN implements the Addr interface.
func (addr *Addr8) SetN(n uint) {
addr[0] = uint8(n)
}
// Slice implements the Addr interface.
func (addr Addr8) Slice() []byte { return addr[:] }

// N implements the Addr interface.
func (addr Addr16) N() uint {
return uint(addr[0]) | uint(addr[1])<<8
}

// SetN implements the Addr interface.
func (addr *Addr16) SetN(n uint) {
addr[0] = uint8(n)
addr[1] = uint8(n >> 8)
}

// N implements the Addr interface.
func (addr Addr24) N() uint {
return uint(addr[0]) | uint(addr[1])<<8 | uint(addr[2])<<16
}

// SetN implements the Addr interface.
func (addr *Addr24) SetN(n uint) {
addr[0] = uint8(n)
addr[1] = uint8(n >> 8)
addr[2] = uint8(n >> 16)
}

func (addr Addr16) LowOctet() uint8 { return addr[0] }
func (addr Addr16) HighOctet() uint8 { return addr[1] }
func (addr Addr24) LowOctet() uint8 { return addr[0] }
Expand Down
5 changes: 3 additions & 2 deletions monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@ type Monitor[Addr info.Addr] struct {

// NextAddr gets the followup in an info.Sequence.
func nextAddr[T info.Addr](addr T) T {
addr.SetN(addr.N() + 1)
return addr
// overflow ignored (as unspecified behaviour)
sum, _ := info.NewAddrN[T](addr.N() + 1)
return sum
}

var errNotMonitor = errors.New("part5: ASDU type is monitor information")
Expand Down

0 comments on commit 8c94f8e

Please sign in to comment.