// This code was initially generated by ffjson <https://github.com/pquerna/ffjson>
// This code was generated via the following steps:
// $ go get -u github.com/pquerna/ffjson
// $ make BIND_DIR=. shell
// $ ffjson pkg/jsonlog/jsonlog.go
// $ mv pkg/jsonglog/jsonlog_ffjson.go pkg/jsonlog/jsonlog_marshalling.go
//
// It has been modified to improve the performance of time marshalling to JSON
// and to clean it up.
// Should this code need to be regenerated when the JSONLog struct is changed,
// the relevant changes which have been made are:
// import (
//        "bytes"
//-
//        "unicode/utf8"
// )
//
// func (mj *JSONLog) MarshalJSON() ([]byte, error) {
//@@ -20,13 +16,13 @@ func (mj *JSONLog) MarshalJSON() ([]byte, error) {
//        }
//        return buf.Bytes(), nil
// }
//+
// func (mj *JSONLog) MarshalJSONBuf(buf *bytes.Buffer) error {
//-       var err error
//-       var obj []byte
//-       var first bool = true
//-       _ = obj
//-       _ = err
//-       _ = first
//+       var (
//+               err       error
//+               timestamp string
//+               first     bool = true
//+       )
//        buf.WriteString(`{`)
//        if len(mj.Log) != 0 {
//                if first == true {
//@@ -52,11 +48,11 @@ func (mj *JSONLog) MarshalJSONBuf(buf *bytes.Buffer) error {
//                buf.WriteString(`,`)
//        }
//        buf.WriteString(`"time":`)
//-       obj, err = mj.Created.MarshalJSON()
//+       timestamp, err = FastTimeMarshalJSON(mj.Created)
//        if err != nil {
//                return err
//        }
//-       buf.Write(obj)
//+       buf.WriteString(timestamp)
//        buf.WriteString(`}`)
//        return nil
// }
// @@ -81,9 +81,10 @@ func (mj *JSONLog) MarshalJSONBuf(buf *bytes.Buffer) error {
//         if len(mj.Log) != 0 {
// -                if first == true {
// -                       first = false
// -               } else {
// -                       buf.WriteString(`,`)
// -               }
// +               first = false
//                 buf.WriteString(`"log":`)
//                 ffjsonWriteJSONString(buf, mj.Log)
//         }

package jsonlog

import (
	"bytes"
	"unicode/utf8"
)

// MarshalJSON marshals the JSONLog.
func (mj *JSONLog) MarshalJSON() ([]byte, error) {
	var buf bytes.Buffer
	buf.Grow(1024)
	if err := mj.MarshalJSONBuf(&buf); err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

// MarshalJSONBuf marshals the JSONLog and stores the result to a bytes.Buffer.
func (mj *JSONLog) MarshalJSONBuf(buf *bytes.Buffer) error {
	var (
		err       error
		timestamp string
		first     = true
	)
	buf.WriteString(`{`)
	if len(mj.Log) != 0 {
		first = false
		buf.WriteString(`"log":`)
		ffjsonWriteJSONString(buf, mj.Log)
	}
	if len(mj.Stream) != 0 {
		if first {
			first = false
		} else {
			buf.WriteString(`,`)
		}
		buf.WriteString(`"stream":`)
		ffjsonWriteJSONString(buf, mj.Stream)
	}
	if !first {
		buf.WriteString(`,`)
	}
	buf.WriteString(`"time":`)
	timestamp, err = FastTimeMarshalJSON(mj.Created)
	if err != nil {
		return err
	}
	buf.WriteString(timestamp)
	buf.WriteString(`}`)
	return nil
}

func ffjsonWriteJSONString(buf *bytes.Buffer, s string) {
	const hex = "0123456789abcdef"

	buf.WriteByte('"')
	start := 0
	for i := 0; i < len(s); {
		if b := s[i]; b < utf8.RuneSelf {
			if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' {
				i++
				continue
			}
			if start < i {
				buf.WriteString(s[start:i])
			}
			switch b {
			case '\\', '"':
				buf.WriteByte('\\')
				buf.WriteByte(b)
			case '\n':
				buf.WriteByte('\\')
				buf.WriteByte('n')
			case '\r':
				buf.WriteByte('\\')
				buf.WriteByte('r')
			default:

				buf.WriteString(`\u00`)
				buf.WriteByte(hex[b>>4])
				buf.WriteByte(hex[b&0xF])
			}
			i++
			start = i
			continue
		}
		c, size := utf8.DecodeRuneInString(s[i:])
		if c == utf8.RuneError && size == 1 {
			if start < i {
				buf.WriteString(s[start:i])
			}
			buf.WriteString(`\ufffd`)
			i += size
			start = i
			continue
		}

		if c == '\u2028' || c == '\u2029' {
			if start < i {
				buf.WriteString(s[start:i])
			}
			buf.WriteString(`\u202`)
			buf.WriteByte(hex[c&0xF])
			i += size
			start = i
			continue
		}
		i += size
	}
	if start < len(s) {
		buf.WriteString(s[start:])
	}
	buf.WriteByte('"')
}