Repository: jhump/protoreflect (go)

Issue:
UTF-8 Byte Order Marks causes parser errors
When a .proto file starts with the UTF-8 byte order marks, protoparse returns an unexpected syntax error:

```
foo:1:1: syntax error: unexpected $unk
```

This snippet reproduces the error:
```go
package main

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"

	"github.com/jhump/protoreflect/desc/protoparse"
)

func main() {
	file := append([]byte{0xEF, 0xBB, 0xBF}, []byte(`syntax = "proto3";`)...)
	parser := &protoparse.Parser{
		Accessor: func(_ string) (closer io.ReadCloser, e error) {
			return ioutil.NopCloser(bytes.NewReader(file)), nil
		},
	}

	_, err := parser.ParseFiles("foo")
	if err != nil {
		fmt.Println("Error!", err)
		return
	}
	fmt.Println("Success!")
}
```
Note the UTF-8 BOM at the start of the otherwise valid proto3 file. This used to work, and seems to have been introduced sometime after https://github.com/jhump/protoreflect/commit/9a9113f80b5726d48e1a25b035161cc5c46714c1, as that was the commit present in `buf` 0.18.0, which successfully parsed this.

Pull request description:
protoparse: support file starting with BOM
Resolves #342 

Patch:
diff --git a/desc/protoparse/lexer.go b/desc/protoparse/lexer.go
index ce3d2f6..a094fe2 100644
--- a/desc/protoparse/lexer.go
+++ b/desc/protoparse/lexer.go
@@ -60,9 +60,19 @@ type protoLex struct {
 	comments   []comment
 }
 
+var utf8Bom = []byte{0xEF, 0xBB, 0xBF}
+
 func newLexer(in io.Reader, filename string, errs *errorHandler) *protoLex {
+	br := bufio.NewReader(in)
+
+	// if file has UTF8 byte order marker preface, consume it
+	marker, err := br.Peek(3)
+	if err == nil && bytes.Equal(marker, utf8Bom) {
+		_, _ = br.Discard(3)
+	}
+
 	return &protoLex{
-		input:    &runeReader{rr: bufio.NewReader(in)},
+		input:    &runeReader{rr: br},
 		filename: filename,
 		errs:     errs,
 	}


Test patch:
diff --git a/desc/protoparse/validate_test.go b/desc/protoparse/validate_test.go
index 3963f97..fad6a97 100644
--- a/desc/protoparse/validate_test.go
+++ b/desc/protoparse/validate_test.go
@@ -16,6 +16,11 @@ func TestBasicValidation(t *testing.T) {
 			contents: `message Foo { optional double bar = 1 [default = -18446744073709551615]; }`,
 			succeeds: true,
 		},
+		{
+			// with byte order marker
+			contents: string([]byte{0xEF, 0xBB, 0xBF}) + `message Foo { optional double bar = 1 [default = -18446744073709551615]; }`,
+			succeeds: true,
+		},
 		{
 			contents: `message Foo { optional double bar = 1 [default = 18446744073709551616]; }`,
 			succeeds: true,