protgen/proto/proto.go

137 lines
2.7 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,
}
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)
}