summaryrefslogtreecommitdiff
path: root/load.go
diff options
context:
space:
mode:
Diffstat (limited to 'load.go')
-rw-r--r--load.go170
1 files changed, 170 insertions, 0 deletions
diff --git a/load.go b/load.go
new file mode 100644
index 0000000..1fbd2ca
--- /dev/null
+++ b/load.go
@@ -0,0 +1,170 @@
+package config
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "strings"
+
+ "google.golang.org/protobuf/encoding/protojson"
+ "google.golang.org/protobuf/encoding/prototext"
+ "google.golang.org/protobuf/proto"
+)
+
+func LoadPB(pb proto.Message) error {
+ return ReLoad(pb)
+}
+
+// uses the version to die. This is needed because loading binary
+// protobuf files with rearranged messages is indeterminate
+func ReLoad(pb proto.Message) error {
+ fullname, err := GetFilename(pb)
+ if (fullname == "") || (err != nil) {
+ panic("config.LoadPB() got blank filename = ''")
+ }
+ // this code needs work
+ newver, pbver, err := VersionCheckFile(pb, fullname)
+ if errors.Is(err, os.ErrNotExist) {
+ //
+ err = SaveToFilename(pb, fullname)
+ return err
+ }
+ if errors.Is(err, VersionMismatch) || (newver != pbver) {
+ fmt.Println("")
+ fmt.Printf("VERSION new '%s' != cur PB '%s'\n", newver, pbver)
+ fmt.Println("")
+ fmt.Println("Your protobuf file is old and can not be loaded")
+ fmt.Println("your application must decide how to handle this (delete or fix)")
+ fmt.Println("always die here. application is broken")
+ fmt.Println("You must delete or convert the file", fullname)
+ fmt.Println("")
+ // probably should ALWAYS PANIC HERE
+ // upon further study, always die here is better than not
+ s := fmt.Sprintf("protobuf version wrong. delete or fix %s", fullname)
+ panic(s)
+ }
+ if err != nil {
+ // return to let the application figure this out
+ return err
+ }
+ return nil
+}
+
+func LoadFromFilename(pb proto.Message, 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
+ SetFilename(pb, fullname)
+ 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
+ }
+
+ if fn, err := GetFilename(pb); err != nil {
+ if fn != fullname {
+ SetFilename(pb, fullname)
+ }
+ }
+ 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
+ }
+
+ if fn, err := GetFilename(pb); err != nil {
+ if fn != fullname {
+ SetFilename(pb, fullname)
+ }
+ }
+ 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
+}
+
+/* left this here to remind myself just how dumb I can be
+
+// dumb but simple to read logic
+func missingConfig(fullname string) error {
+ data1, err1 := os.ReadFile(fullname)
+ if !errors.Is(err1, os.ErrNotExist) {
+ return err1
+ }
+
+ data2, err2 := os.ReadFile(fullname + ".json")
+ if !errors.Is(err2, os.ErrNotExist) {
+ return err2
+ }
+ if errors.Is(err1, os.ErrNotExist) && errors.Is(err2, os.ErrNotExist) {
+ return os.ErrNotExist
+ }
+ if (len(data1) == 0) && (len(data2) == 0) {
+ return ErrEmpty
+ }
+ return nil
+}
+*/