package jsoniter

import (
	
)

// stream is a io.Writer like object, with JSON specific write functions.
// Error is not returned as return value, but stored as Error member on this stream instance.
type Stream struct {
	cfg        *frozenConfig
	out        io.Writer
	buf        []byte
	Error      error
	indention  int
	Attachment interface{} // open for customized encoder
}

// NewStream create new stream instance.
// cfg can be jsoniter.ConfigDefault.
// out can be nil if write to internal buffer.
// bufSize is the initial size for the internal buffer in bytes.
func ( API,  io.Writer,  int) *Stream {
	return &Stream{
		cfg:       .(*frozenConfig),
		out:       ,
		buf:       make([]byte, 0, ),
		Error:     nil,
		indention: 0,
	}
}

// Pool returns a pool can provide more stream with same configuration
func ( *Stream) () StreamPool {
	return .cfg
}

// Reset reuse this stream instance by assign a new writer
func ( *Stream) ( io.Writer) {
	.out = 
	.buf = .buf[:0]
}

// Available returns how many bytes are unused in the buffer.
func ( *Stream) () int {
	return cap(.buf) - len(.buf)
}

// Buffered returns the number of bytes that have been written into the current buffer.
func ( *Stream) () int {
	return len(.buf)
}

// Buffer if writer is nil, use this method to take the result
func ( *Stream) () []byte {
	return .buf
}

// SetBuffer allows to append to the internal buffer directly
func ( *Stream) ( []byte) {
	.buf = 
}

// Write writes the contents of p into the buffer.
// It returns the number of bytes written.
// If nn < len(p), it also returns an error explaining
// why the write is short.
func ( *Stream) ( []byte) ( int,  error) {
	.buf = append(.buf, ...)
	if .out != nil {
		,  = .out.Write(.buf)
		.buf = .buf[:]
		return
	}
	return len(), nil
}

// WriteByte writes a single byte.
func ( *Stream) ( byte) {
	.buf = append(.buf, )
}

func ( *Stream) ( byte,  byte) {
	.buf = append(.buf, , )
}

func ( *Stream) ( byte,  byte,  byte) {
	.buf = append(.buf, , , )
}

func ( *Stream) ( byte,  byte,  byte,  byte) {
	.buf = append(.buf, , , , )
}

func ( *Stream) ( byte,  byte,  byte,  byte,  byte) {
	.buf = append(.buf, , , , , )
}

// Flush writes any buffered data to the underlying io.Writer.
func ( *Stream) () error {
	if .out == nil {
		return nil
	}
	if .Error != nil {
		return .Error
	}
	,  := .out.Write(.buf)
	if  != nil {
		if .Error == nil {
			.Error = 
		}
		return 
	}
	.buf = .buf[:0]
	return nil
}

// WriteRaw write string out without quotes, just like []byte
func ( *Stream) ( string) {
	.buf = append(.buf, ...)
}

// WriteNil write null to stream
func ( *Stream) () {
	.writeFourBytes('n', 'u', 'l', 'l')
}

// WriteTrue write true to stream
func ( *Stream) () {
	.writeFourBytes('t', 'r', 'u', 'e')
}

// WriteFalse write false to stream
func ( *Stream) () {
	.writeFiveBytes('f', 'a', 'l', 's', 'e')
}

// WriteBool write true or false into stream
func ( *Stream) ( bool) {
	if  {
		.WriteTrue()
	} else {
		.WriteFalse()
	}
}

// WriteObjectStart write { with possible indention
func ( *Stream) () {
	.indention += .cfg.indentionStep
	.writeByte('{')
	.writeIndention(0)
}

// WriteObjectField write "field": with possible indention
func ( *Stream) ( string) {
	.WriteString()
	if .indention > 0 {
		.writeTwoBytes(':', ' ')
	} else {
		.writeByte(':')
	}
}

// WriteObjectEnd write } with possible indention
func ( *Stream) () {
	.writeIndention(.cfg.indentionStep)
	.indention -= .cfg.indentionStep
	.writeByte('}')
}

// WriteEmptyObject write {}
func ( *Stream) () {
	.writeByte('{')
	.writeByte('}')
}

// WriteMore write , with possible indention
func ( *Stream) () {
	.writeByte(',')
	.writeIndention(0)
}

// WriteArrayStart write [ with possible indention
func ( *Stream) () {
	.indention += .cfg.indentionStep
	.writeByte('[')
	.writeIndention(0)
}

// WriteEmptyArray write []
func ( *Stream) () {
	.writeTwoBytes('[', ']')
}

// WriteArrayEnd write ] with possible indention
func ( *Stream) () {
	.writeIndention(.cfg.indentionStep)
	.indention -= .cfg.indentionStep
	.writeByte(']')
}

func ( *Stream) ( int) {
	if .indention == 0 {
		return
	}
	.writeByte('\n')
	 := .indention - 
	for  := 0;  < ; ++ {
		.buf = append(.buf, ' ')
	}
}