143 lines
2.9 KiB
Go
143 lines
2.9 KiB
Go
package proto
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"log"
|
|
"strconv"
|
|
"text/template"
|
|
"unicode"
|
|
)
|
|
|
|
type HexByte byte
|
|
|
|
type ProtocolHeader struct {
|
|
StartByte HexByte `json:"start_byte"`
|
|
MessageLength int `json:"message_length"`
|
|
MaxPayload int `json:"max_payload"`
|
|
Checksum string `json:"checksum"`
|
|
}
|
|
|
|
type ProtoMessage struct {
|
|
Name string `json:"name"`
|
|
ID HexByte `json:"id"`
|
|
Payload []ProtoMessagePayload `json:"payload,omitempty"` // optional falls kein payload
|
|
}
|
|
|
|
type ProtoMessagePayload struct {
|
|
Name string `json:"name"`
|
|
DataType string `json:"type"`
|
|
ArrayLength int `json:"array,omitempty"`
|
|
}
|
|
|
|
type Proto struct {
|
|
ProtocolHeader ProtocolHeader `json:"protocol"`
|
|
ESP_TO_PC []ProtoMessage `json:"messages_esp_to_pc"`
|
|
PC_TO_ESP []ProtoMessage `json:"messages_pc_to_esp"`
|
|
}
|
|
|
|
func (h *HexByte) UnmarshalJSON(data []byte) error {
|
|
var s string
|
|
if err := json.Unmarshal(data, &s); err != nil { // turn into go string
|
|
return err
|
|
}
|
|
|
|
i, err := strconv.ParseUint(s, 0, 8)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
*h = HexByte(i)
|
|
return nil
|
|
}
|
|
|
|
type Cenum struct {
|
|
EnumName string
|
|
Entries []ProtoMessage
|
|
}
|
|
|
|
type PayloadStruct struct {
|
|
Name string
|
|
Entries []ProtoMessagePayload
|
|
}
|
|
|
|
type CStyleData struct {
|
|
CenumPCTOESP Cenum
|
|
CenumESPTOPC Cenum
|
|
PayloadStructs []PayloadStruct
|
|
MessagesPCtoESP []ProtoMessage
|
|
MessagesESPtoPC []ProtoMessage
|
|
}
|
|
|
|
func CreateCStyle(proto *Proto) (string, error) {
|
|
funcs := template.FuncMap{
|
|
"snake": toSnakeCase,
|
|
"isLast": isLast,
|
|
}
|
|
|
|
tmpl, err := template.New("all").Funcs(funcs).ParseGlob("templates/*.tmpl")
|
|
if err != nil {
|
|
log.Fatalf("failed to parse templates: %v", err)
|
|
}
|
|
|
|
payloads := []PayloadStruct{}
|
|
|
|
for _, payload := range proto.PC_TO_ESP {
|
|
tmp := PayloadStruct{
|
|
Name: payload.Name,
|
|
Entries: payload.Payload,
|
|
}
|
|
payloads = append(payloads, tmp)
|
|
}
|
|
|
|
for _, payload := range proto.ESP_TO_PC {
|
|
tmp := PayloadStruct{
|
|
Name: payload.Name,
|
|
Entries: payload.Payload,
|
|
}
|
|
payloads = append(payloads, tmp)
|
|
}
|
|
|
|
var data = CStyleData{
|
|
CenumPCTOESP: Cenum{
|
|
EnumName: "PC_TO_ESP_MESSAGE_IDS",
|
|
Entries: proto.PC_TO_ESP,
|
|
},
|
|
CenumESPTOPC: Cenum{
|
|
EnumName: "ESP_TO_PC_MESSAGE_IDS",
|
|
Entries: proto.ESP_TO_PC,
|
|
},
|
|
PayloadStructs: payloads,
|
|
MessagesPCtoESP: proto.PC_TO_ESP,
|
|
MessagesESPtoPC: proto.ESP_TO_PC,
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
err = tmpl.ExecuteTemplate(&buf, "cpart", data)
|
|
if err != nil {
|
|
log.Printf("Error Rendering template: %v", err)
|
|
}
|
|
|
|
return buf.String(), nil
|
|
}
|
|
|
|
func toSnakeCase(str string) string {
|
|
var out []rune
|
|
for i, r := range str {
|
|
if unicode.IsUpper(r) {
|
|
if i != 0 {
|
|
out = append(out, '_')
|
|
}
|
|
out = append(out, unicode.ToLower(r))
|
|
} else {
|
|
out = append(out, r)
|
|
}
|
|
}
|
|
return string(out)
|
|
}
|
|
|
|
// just a helper function, pass the length of your array and your current index
|
|
func isLast(datalen int, index int) bool {
|
|
return index == datalen-1
|
|
}
|