Browse Source

codecgen: fix packageName to use valid go identifier

Previously, an import path like github.com/ugorji/go-codec would fail
during codecgen. This is because we used the last part of the path to
determine the packageName. However, package names can only contain
unicode letters, digits and underscores.

We now take the last path, and coerce it into a valid go identifier.

Fixes #127
Ugorji Nwoke 10 years ago
parent
commit
53d1166d60
1 changed files with 23 additions and 1 deletions
  1. 23 1
      codec/gen.go

+ 23 - 1
codec/gen.go

@@ -21,6 +21,8 @@ import (
 	"sync"
 	"text/template"
 	"time"
+	"unicode"
+	"unicode/utf8"
 )
 
 // ---------------------------------------------------
@@ -377,7 +379,7 @@ func (x *genRunner) genRefPkgs(t reflect.Type) {
 				x.imn[tpkg] = tpkg
 			} else {
 				x.imc++
-				x.imn[tpkg] = "pkg" + strconv.FormatUint(x.imc, 10) + "_" + tpkg[idx+1:]
+				x.imn[tpkg] = "pkg" + strconv.FormatUint(x.imc, 10) + "_" + genGoIdentifier(tpkg[idx+1:], false)
 			}
 		}
 	}
@@ -1639,6 +1641,26 @@ func genImportPath(t reflect.Type) (s string) {
 	return
 }
 
+// A go identifier is (letter|_)[letter|number|_]*
+func genGoIdentifier(s string, checkFirstChar bool) string {
+	b := make([]byte, 0, len(s))
+	t := make([]byte, 4)
+	var n int
+	for i, r := range s {
+		if checkFirstChar && i == 0 && !unicode.IsLetter(r) {
+			b = append(b, '_')
+		}
+		// r must be unicode_letter, unicode_digit or _
+		if unicode.IsLetter(r) || unicode.IsNumber(r) {
+			n = utf8.EncodeRune(t, r)
+			b = append(b, t[:n]...)
+		} else {
+			b = append(b, '_')
+		}
+	}
+	return string(b)
+}
+
 func genNonPtr(t reflect.Type) reflect.Type {
 	for t.Kind() == reflect.Ptr {
 		t = t.Elem()