浏览代码

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 年之前
父节点
当前提交
53d1166d60
共有 1 个文件被更改,包括 23 次插入1 次删除
  1. 23 1
      codec/gen.go

+ 23 - 1
codec/gen.go

@@ -21,6 +21,8 @@ import (
 	"sync"
 	"sync"
 	"text/template"
 	"text/template"
 	"time"
 	"time"
+	"unicode"
+	"unicode/utf8"
 )
 )
 
 
 // ---------------------------------------------------
 // ---------------------------------------------------
@@ -377,7 +379,7 @@ func (x *genRunner) genRefPkgs(t reflect.Type) {
 				x.imn[tpkg] = tpkg
 				x.imn[tpkg] = tpkg
 			} else {
 			} else {
 				x.imc++
 				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
 	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 {
 func genNonPtr(t reflect.Type) reflect.Type {
 	for t.Kind() == reflect.Ptr {
 	for t.Kind() == reflect.Ptr {
 		t = t.Elem()
 		t = t.Elem()