{{ define "packet" }} {{- $structName := camelCase .Name true}} {{- /* generate any bitfield structs */ -}} {{range .Data -}} {{ if .Bits -}} {{- $bfname := (printf "%s%s" $structName (camelCase .Name true)) }} type {{$bfname}} struct { {{- range $el := .Bits}} {{camelCase $el.Name true}} bool `json:"{{$el.Name}}"` {{- end}} } func (p *{{$bfname}}) Marshal() byte { var b byte {{- range $idx, $el := .Bits}} {{- $bitName := camelCase $el.Name true}} if p.{{$bitName}} { b |= 1 << {{$idx}} } {{- end}} return b } func (p *{{$bfname}}) Unmarshal(b byte) { {{- range $idx, $el := .Bits}} {{- $bitName := camelCase $el.Name true }} p.{{$bitName}} = (b & (1 << {{ $idx }})) != 0 {{- end}} } {{end}} {{- end}} // {{$structName}} is {{.Description}} type {{$structName}} struct { {{- range .Data}} {{- if .Units }} // {{.Conversion}} {{.Units}} {{- end }} {{ .ToStructMember $structName }} `json:"{{.Name}}"` {{- end}} {{- if .Repeat }} // Idx is the packet index. The accepted range is 0-{{.Repeat}} Idx uint32 `json:"idx"` {{- end }} } func (p *{{$structName}}) CANId() (uint32, error) { {{- if .Repeat }} if p.Idx >= {{.Repeat}} { return 0, errors.New("invalid packet index") } return {{ printf "0x%X" .Id }} + p.Idx, nil {{- else }} return {{ printf "0x%X" .Id }}, nil {{- end }} } func (p *{{$structName}}) Size() uint { return {{.CalcSize}} } func (p *{{$structName}}) MarshalPacket() ([]byte, error) { b := make([]byte, {{ .CalcSize }}) {{.MakeMarshal}} return b, nil } func (p *{{$structName}}) UnmarshalPacket(b []byte) error { {{.MakeUnmarshal}} return nil } func (p *{{$structName}}) String() string { return "{{ .Name }}" } {{ end }} {{- /* begin actual file template */ -}} // generated by gen_skylab.go at {{ Time }} DO NOT EDIT! package skylab import ( "errors" "encoding/binary" "encoding/json" ) type SkylabId uint32 const ( {{- range .Packets }} {{camelCase .Name true}}Id SkylabId = {{.Id | printf "0x%X"}} {{- end}} ) // list of every packet ID. can be used for O(1) checks. var idMap = map[uint32]bool{ {{ range $p := .Packets -}} {{ if $p.Repeat }} {{ range $idx := Nx (int $p.Id) $p.Repeat $p.Offset -}} {{ $idx | printf "0x%X"}}: true, {{ end }} {{- else }} {{ $p.Id | printf "0x%X" }}: true, {{- end}} {{- end}} } // FromCanFrame creates a Packet from a given CAN ID and data payload. // If the CAN ID is unknown, it will return an error. func FromCanFrame(id uint32, data []byte) (Packet, error) { if !idMap[id] { return nil, errors.New("Unknown Id") } switch id { {{- range $p := .Packets }} {{- if $p.Repeat }} case {{ Nx (int $p.Id) $p.Repeat $p.Offset | mapf "0x%X" | strJoin ", " -}}: var res = &{{camelCase $p.Name true}}{} res.UnmarshalPacket(data) res.Idx = id - {{$p.Id | printf "0x%X" }} return res, nil {{- else }} case {{ $p.Id | printf "0x%X" }}: var res = &{{camelCase $p.Name true}}{} res.UnmarshalPacket(data) return res, nil {{- end}} {{- end}} } return nil, errors.New("failed to match Id, something is really wrong!") } func FromJson (raw []byte) (Packet, error) { // attempt to parse the JSON to a JSONPacket jp := &JSONPacket{} err := json.Unmarshal(raw, jp) if err != nil { return nil, err } switch jp.Id { {{- range $p := .Packets }} {{- if $p.Repeat }} case {{ Nx (int $p.Id) $p.Repeat $p.Offset | mapf "0x%X" | strJoin ", " -}}: var res = &{{camelCase $p.Name true}}{} err := json.Unmarshal(jp.Data, res) res.Idx = jp.Id - {{ $p.Id | printf "0x%X" }} return res, err {{- else }} case {{ $p.Id | printf "0x%X" }}: var res = &{{camelCase $p.Name true}}{} err := json.Unmarshal(jp.Data, res) return res, err {{- end }} {{- end }} } return nil, errors.New("aaa") } {{range .Packets -}} {{template "packet" .}} {{- end}}