summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--example/fruit.proto78
-rw-r--r--example/fruit.proto.new14
-rw-r--r--file.proto.new103
-rw-r--r--protoReformat.go44
4 files changed, 182 insertions, 57 deletions
diff --git a/example/fruit.proto b/example/fruit.proto
index 6df0b89..c546fd4 100644
--- a/example/fruit.proto
+++ b/example/fruit.proto
@@ -16,61 +16,63 @@ package main;
import "google/protobuf/timestamp.proto"; // Import the well-known type for Timestamp
message Apple {
- string name = 1; // `autogenpb:unique` // generates SortByxxx() and AppendUnique() functions
- string genus = 2; // `autogenpb:unique` // generates same thing here but SortByGenus()
- google.protobuf.Timestamp ctime = 3; // when the apple was born
+ string name = 1; // `autogenpb:unique` // generates SortByxxx() and AppendUnique() functions
+ string genus = 2; // `autogenpb:unique` // generates same thing here but SortByGenus()
+ google.protobuf.Timestamp ctime = 3; // when the apple was born
}
message Apples {
- string name = 1; // `autogenpb:unique` // generates SortByxxx() and AppendUnique() functions
- string genus = 2; // `autogenpb:unique` // generates same thing here but SortByGenus()
- repeated Apple apples = 3;
+ string name = 1; // `autogenpb:unique` // generates SortByxxx() and AppendUnique() functions
+ string genus = 2; // `autogenpb:unique` // generates same thing here but SortByGenus()
+ repeated Apple apples = 3;
}
-message Pear { // `autogenpb:nomutex`
- string name = 1; // `autogenpb:sort`
- string favorite = 2; // `autogenpb:sort` `autogenpb:unique`
+message Pear { // `autogenpb:nomutex`
+ string name = 1; // `autogenpb:sort`
+ string favorite = 2; // `autogenpb:sort` `autogenpb:unique`
}
-message Pears { // `autogenpb:nomutex`
- string name = 1; // `autogenpb:sort`
- string favorite = 2; // `autogenpb:sort` `autogenpb:unique`
- repeated Pear pears = 3;
+message Pears { // `autogenpb:nomutex`
+ string name = 1; // `autogenpb:sort`
+ string favorite = 2; // `autogenpb:sort` `autogenpb:unique`
+ repeated Pear pears = 3;
}
-message Banana { // `autogenpb:nomutex`
- repeated string name = 1; // `autogenpb:sort`
- string favorite = 2; // `autogenpb:sort` `autogenpb:unique`
- string country = 3; // `autogenpb:sort`
+message Banana { // `autogenpb:nomutex`
+ repeated string name = 1; // `autogenpb:sort`
+ string favorite = 2; // `autogenpb:sort` `autogenpb:unique`
+ string country = 3; // `autogenpb:sort`
}
-message Basket { // `autogenpb:nomutex`
- repeated string name = 1; // `autogenpb:sort` `autogenpb:unique`
- string favorite = 2; // `autogenpb:sort` `autogenpb:unique`
- int64 price = 3; // `autogenpb:sort`
- repeated Banana banna = 4;
- repeated Pear pears = 5;
- repeated Apple stacks = 6;
+message Basket { // `autogenpb:nomutex`
+ repeated string name = 1; // `autogenpb:sort` `autogenpb:unique`
+ string favorite = 2; // `autogenpb:sort` `autogenpb:unique`
+ int64 price = 3; // `autogenpb:sort`
+ // here for testing padding
+
+ repeated Banana banna = 4;
+ repeated Pear pears = 5;
+ repeated Apple stacks = 6;
}
// "Fruit" must exist. you can put anything in it
message Fruit {
- string brand = 1; // `autogenpb:unique` `autogenpb:sort`
- Apple apples = 2;
- repeated Pear pears = 3;
- string UPC = 4; // `autogenpb:sort` `autogenpb:unique`
- string city = 5; // `autogenpb:sort`
- Pears notpears = 6;
- Pears fakepears = 7;
- repeated Basket gifts = 8;
+ string brand = 1; // `autogenpb:unique` `autogenpb:sort`
+ Apple apples = 2;
+ repeated Pear pears = 3;
+ string UPC = 4; // `autogenpb:sort` `autogenpb:unique`
+ string city = 5; // `autogenpb:sort`
+ Pears notpears = 6;
+ Pears fakepears = 7;
+ repeated Basket gifts = 8;
}
// "Fruits" MUST EXIST and start exactly this way
// It must be "Fruit" + 's' and must match the name of this file: "fruit.proto"
-message Fruits { // `autogenpb:marshal` `autogenpb:mutex`
- string uuid = 1; // `autogenpb:uuid:be926ad9-f07f-484c-adf2-d96eeabf3079`
- string version = 2; // `autogenpb:version:v0.0.1`
- repeated Fruit Fruits = 3; // THIS MUST BE "Fruit" and then "Fruit" + "s"
- int64 cost = 4; // you can add additional things here but the three lines above must conform to the standard above
- map<string, string> junk = 5;
+message Fruits { // `autogenpb:marshal` `autogenpb:mutex`
+ string uuid = 1; // `autogenpb:uuid:be926ad9-f07f-484c-adf2-d96eeabf3079`
+ string version = 2; // `autogenpb:version:v0.0.1`
+ repeated Fruit Fruits = 3; // THIS MUST BE "Fruit" and then "Fruit" + "s"
+ int64 cost = 4; // you can add additional things here but the three lines above must conform to the standard above
+ map<string, string> junk = 5;
}
diff --git a/example/fruit.proto.new b/example/fruit.proto.new
index f9f39a0..78f9c22 100644
--- a/example/fruit.proto.new
+++ b/example/fruit.proto.new
@@ -45,12 +45,14 @@ message Banana { // `autogenpb:nomutex`
}
message Basket { // `autogenpb:nomutex`
- repeated string name = 1; // `autogenpb:sort` `autogenpb:unique`
- string favorite = 2; // `autogenpb:sort` `autogenpb:unique`
- int64 price = 3; // `autogenpb:sort`
- repeated Banana banna = 4;
- repeated Pear pears = 5;
- repeated Apple stacks = 6;
+ repeated string name = 1; // `autogenpb:sort` `autogenpb:unique`
+ string favorite = 2; // `autogenpb:sort` `autogenpb:unique`
+ int64 price = 3; // `autogenpb:sort`
+ //
+
+ repeated Banana banna = 4;
+ repeated Pear pears = 5;
+ repeated Apple stacks = 6;
}
// "Fruit" must exist. you can put anything in it
diff --git a/file.proto.new b/file.proto.new
new file mode 100644
index 0000000..1bba651
--- /dev/null
+++ b/file.proto.new
@@ -0,0 +1,103 @@
+syntax = "proto3";
+
+// Look at "example/fruit.proto" not this file
+
+// this file is actually used by autogenpb
+
+// here are some docs, but probably it's just easier to run
+// autogenpb on this file and see what gets autogenerated
+// in this directory. All autogenerated files are named *.pb.go
+
+// the 'uuid' standard at the end is an experiment
+// establish a way to identify arbitrary .pb files
+
+// You can generate Marshal & Unmarshal for any struct (message) you want
+// You can generate SortBy and Append functions ONLY FOR 'repeated <message>'
+// Also, those structs must be defined in the same file
+// Additionally, you must use `autogenpb:mutex` on the parent struct.
+// The autogenerated code requires a RW mutex and autogenpb will insert it into the struct
+
+package main;
+
+//
+// below are the actual structs autogen uses
+// autogen parses the .proto file and then store the information
+// it needs in these protobuf files, then it processes the
+// protobuf files to write out *.sort.pb.go and *.marshal.pb.go files
+//
+message MsgVar {
+ string varName = 1; // the variable name
+ string varType = 2; // the variable type
+ bool isRepeated = 3; // does the variable repeate
+ bool hasSort = 4; // marked with sort
+ bool hasUnique = 5; // marked with unique
+}
+
+message MsgName {
+ string name = 1; // the name of the message aka struct. for this example: "Shelf"
+ string lockname = 2; // name of the lockfile. ends in Mu
+ bool doMarshal = 3; // if msg struct should have Marshal & Unmarshal functions
+ bool doMutex = 4; // true if a mutex is needed for the message struct
+ bool doProtocMutex = 5; // an experiment to insert a mutex into the protoc generated msg struct (bad idea?)
+ bool mutexFound = 6; // true if the mutex was added to the protoc pb.go file
+ repeated string sort = 7; // keys to sort on
+ repeated string unique = 8; // if the fields should have AppendUnique() functions
+ repeated MsgVar vars = 9; // store all the vars in the message
+ bool needIter = 10; // true if the sort iterator has not been generated yet
+ bool needAll = 11; // true if the sort iterator has not been generated yet
+ bool noMutex = 12; // only use the global mutex
+}
+
+message Sort {
+ string msgName = 1; // `autogenpb:unique` File
+ string varType = 2; // `autogenpb:unique` MsgName
+ string varName = 3; // `autogenpb:unique` msgNames, sortNames
+ string lockname = 4; //
+ bool needAll = 5; //
+}
+
+message Find {
+ string parent = 1; // `autogenpb:unique` File
+ string varType = 2; // `autogenpb:unique` MsgName
+ string varName = 3; // `autogenpb:unique` msgNames, sortNames
+ bool needAll = 4; //
+}
+
+message File {
+ // `autogenpb:var:w io.Writer`
+ string Package = 1; // whatever the package name is at the top of the .go file
+ string filename = 2; // yellow.proto
+ string pbfilename = 3; // yellow.pb.go
+ string filebase = 4; // yellow
+ string uuid = 5; // the uuid to use in a func NewMsgName()
+ string version = 6; // the version to use in a func NewMsgName()
+ MsgName bases = 7; // the message in "plural" form
+ MsgName base = 8; // the primary repeated message for the master struct
+
+ // every struct in this proto file, this file has: "Apple", "Apples", ... "File", etc...
+ repeated MsgName msgNames = 9;
+ repeated MsgName sortNames = 10; // variables that are repeated can have the standard functions generated (Sort(), etc)
+ map<string, string> iterMap = 11;
+ repeated Sort toSort = 12; // variables that are repeated can have the standard functions generated (Sort(), etc)
+ string goPath = 13; // the version to use in a func NewMsgName()
+}
+
+// I know, I know, the whole point of using protobuf
+// is so you don't need a uuid or versions because it's
+// inherently forward compatable. nonetheless, a simple stubbed out
+// trivial and empty protobuf message can marshal and identify all the files
+// also, this could be used to modify /usr/bin/file /usr/share/magic to identify the files
+// maybe this is already been done and is pointless, but it seems like a good idea
+message Files { // `autogenpb:marshal`
+ string uuid = 1; // `autogenpb:uuid:6c9ae4dd-648d-4b51-9738-bd59fb8fafd5`
+ string version = 2; // `autogenpb:version:v0.0.38`
+ repeated File Files = 3; // an array of each .proto file in the working directory
+}
+
+// this generic message is used by autogen to identify and
+// then dump the uuid and version from any arbitrary .pb file
+message Identify { // `autogenpb:marshal`
+ string uuid = 1; //
+ string version = 2; //
+}
+
diff --git a/protoReformat.go b/protoReformat.go
index 26fae1f..580d920 100644
--- a/protoReformat.go
+++ b/protoReformat.go
@@ -21,15 +21,9 @@ func protoReformat(filename string) error {
return err
}
- pf, err := os.OpenFile(filename+".new", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
- if err != nil {
- log.Info("file open error. permissions?", filename, err)
- return err
- }
- defer pf.Close()
-
var inMessage bool
var curmsg []string
+ var newfile string
// gets the max vartype and varname
for _, line := range strings.Split(string(data), "\n") {
@@ -59,6 +53,7 @@ func protoReformat(filename string) error {
inMessage = true
parts := strings.Fields(line)
if len(parts) > 3 {
+ // hack to actually indent comments on the message line itself. you're welcome
start := parts[0] + " " + parts[1] + " " + parts[2]
end := strings.Join(parts[3:], " ")
offset := maxVarname + maxVartype + 16 - len(start)
@@ -66,29 +61,39 @@ func protoReformat(filename string) error {
hmm := "%s %" + pad + "s %s"
line = fmt.Sprintf(hmm, start, " ", end)
}
- fmt.Fprintln(pf, line)
+ newfile += fmt.Sprintln(line)
continue
}
// find the end of the message
if strings.HasPrefix(line, "}") {
inMessage = false
+ // format and write the last message to the file
for _, newline := range formatMessage(curmsg) {
- fmt.Fprintln(pf, newline)
+ newfile += fmt.Sprintln(newline)
}
- fmt.Fprintln(pf, line)
+ newfile += fmt.Sprintln(line)
curmsg = nil
continue
}
// don't format or change anything when not in a "message {" section
if !inMessage {
- fmt.Fprintln(pf, line)
+ newfile += fmt.Sprintln(line)
continue
}
curmsg = append(curmsg, line)
}
+ pf, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
+ if err != nil {
+ log.Info("file open error. permissions?", filename, err)
+ return err
+ }
+ newfile = strings.TrimSpace(newfile)
+ fmt.Fprintln(pf, newfile)
+ pf.Close()
+
// for i, s := range slices.Backward(pf.ToSort) {
return nil
}
@@ -100,8 +105,8 @@ func formatMessage(curmsg []string) []string {
for _, line := range curmsg {
parts := strings.Split(line, ";")
if len(parts) < 2 {
- log.Info("parse error", line)
- return curmsg
+ // line is blank or just a comment
+ continue
}
vartype, varname, _, _ := tokenMsgVar(line)
@@ -114,6 +119,18 @@ func formatMessage(curmsg []string) []string {
}
for _, line := range curmsg {
+ line = strings.TrimSpace(line)
+ if line == "" {
+ newmsg = append(newmsg, line)
+ continue
+ }
+ if strings.HasPrefix(line, "//") {
+ pad := fmt.Sprintf("%d", maxVartype+maxVarname+21)
+ hmm := "%" + pad + "s %s"
+ line = fmt.Sprintf(hmm, " ", line) // todo: compute 50
+ newmsg = append(newmsg, line)
+ continue
+ }
mt := fmt.Sprintf("%d", maxVartype)
mv := fmt.Sprintf("%d", maxVarname)
@@ -124,6 +141,7 @@ func formatMessage(curmsg []string) []string {
id = id + ";"
newline := fmt.Sprintf(hmm, vartype, varname, id, end)
+ newline = strings.TrimRight(newline, " ")
newmsg = append(newmsg, newline)
}
return newmsg