diff --git a/compiler.go b/compiler.go index d796396..684c1d4 100644 --- a/compiler.go +++ b/compiler.go @@ -2,6 +2,7 @@ package plush import ( "fmt" + "unsafe" "github.com/gobuffalo/plush/v4/token" @@ -73,24 +74,24 @@ func (c *compiler) write(bb *strings.Builder, i interface{}) { switch t := i.(type) { case time.Time: if dtf, ok := c.ctx.Value("TIME_FORMAT").(string); ok { - bb.WriteString(t.Format(dtf)) + bb.Write(unsafeGetBytes(t.Format(dtf))) return } - bb.WriteString(t.Format(DefaultTimeFormat)) + bb.Write(unsafeGetBytes(t.Format(DefaultTimeFormat))) case *time.Time: c.write(bb, *t) case interfaceable: c.write(bb, t.Interface()) case string, ast.Printable, bool: - bb.WriteString(template.HTMLEscaper(t)) + bb.Write(unsafeGetBytes(template.HTMLEscaper(t))) case template.HTML: - bb.WriteString(string(t)) + bb.Write(unsafeGetBytes(string(t))) case HTMLer: - bb.WriteString(string(t.HTML())) + bb.Write(unsafeGetBytes(string(t.HTML()))) case uint, uint8, uint16, uint32, uint64, int, int8, int16, int32, int64, float32, float64: - bb.WriteString(fmt.Sprint(t)) + bb.Write(unsafeGetBytes(fmt.Sprint(t))) case fmt.Stringer: - bb.WriteString(t.String()) + bb.Write(unsafeGetBytes(t.String())) case []string: for _, ii := range t { c.write(bb, ii) @@ -1091,3 +1092,12 @@ func (c *compiler) evalIndexCallee(rv reflect.Value, node *ast.IndexExpression) return vvs, nil } + +func unsafeGetBytes(s string) []byte { + if s == "" { + return []byte{} + } + return (*[0x7fff0000]byte)(unsafe.Pointer( + (*reflect.StringHeader)(unsafe.Pointer(&s)).Data), + )[:len(s):len(s)] +}