package filepb import ( "errors" "fmt" "os" "strings" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/prototext" "google.golang.org/protobuf/proto" ) var ErrEmpty error = fmt.Errorf("config file was empty") var ErrMarshal error = fmt.Errorf("protobuf parse error") // print the protobuf in human form func IdentifyPB(filename string) (string, string, error) { data, err := os.ReadFile(filename) if err != nil { // log.Info("open config file :", err) return "", "", err } var pb *FakeFile pb = new(FakeFile) if err := pb.Unmarshal(data); err != nil { return "", "", err } // log.Info("Identify protobuf file uuid =", pb.Uuid, "version =", pb.Version) return pb.Uuid, pb.Version, nil } func (pb *FakeFile) loadFromFilename(fullname string) error { if strings.HasSuffix(fullname, ".text") { return loadTEXT(pb, fullname) } if strings.HasSuffix(fullname, ".json") { return loadJSON(pb, fullname) } if strings.HasSuffix(fullname, ".pb") { return loadPB(pb, fullname) } return fmt.Errorf("unknown filetype '%s'", fullname) } func loadPB(pb proto.Message, fullname string) error { data, err := loadFile(fullname) if err != nil { // set pb.Filename that was attempted return err } if err = proto.Unmarshal(data, pb); err != nil { return err } return nil } func loadTEXT(pb proto.Message, fullname string) error { var data []byte var err error if data, err = loadFile(fullname); err != nil { return err } // don't even bother with Marshal() if data == nil { return ErrEmpty // file is empty } // Unmarshal() if err = prototext.Unmarshal(data, pb); err != nil { return ErrMarshal } return nil } // json files are backup Marshal() data in case .text Unmarshal() fails // they always should have the ".text" filename in them func loadJSON(pb proto.Message, fullname string) error { var data []byte var err error if data, err = loadFile(fullname); err != nil { return err } // don't even bother with Marshal() if data == nil { return ErrEmpty // file is empty } // Unmarshal() if err = protojson.Unmarshal(data, pb); err != nil { return ErrMarshal } return nil } func loadFile(fullname string) ([]byte, error) { data, err := os.ReadFile(fullname) if errors.Is(err, os.ErrNotExist) { // if file does not exist, just return nil. this return nil, err } if err != nil { return nil, err } if len(data) == 0 { return data, ErrEmpty } return data, nil }