diff options
Diffstat (limited to 'json/write.go')
| -rw-r--r-- | json/write.go | 184 | 
1 files changed, 138 insertions, 46 deletions
| diff --git a/json/write.go b/json/write.go index d024a56..9e349be 100644 --- a/json/write.go +++ b/json/write.go @@ -69,25 +69,40 @@ func (writer *JSONWriter) indent(level int) {  }  func (writer *JSONWriter) write(targetPath []walk.Value, value walk.Value) error { -	diversionPoint := len(writer.path) +	diversionPoint := 0  	for diversionPoint < len(writer.path) && diversionPoint < len(targetPath) && segmentEqual(writer.path[diversionPoint], targetPath[diversionPoint]) {  		diversionPoint += 1  	} -	 +  	switch writer.state {  	case JSONWriterStateBeforeValue:  		goto beforeValue  	case JSONWriterStateAfterValue:  		goto afterValue -	case JSONWriterStateInMap: -		goto inMap  	case JSONWriterStateInArray:  		goto inArray -	default: -		panic("Invalid JSONWriterState") +	case JSONWriterStateInMap: +		goto inMap  	}  	beforeValue: { +		if diversionPoint < len(writer.path) { +			panic("Writing a value before doing a necessary leave") +		} +		if diversionPoint < len(targetPath) { +			segment := targetPath[diversionPoint] +			switch segment.(type) { +			case walk.NumberScalar: +				writer.writer.WriteString("[\n") +				goto inArray +			case walk.StringStructure: +				writer.writer.WriteString("{\n") +				goto inMap +			default: +				panic("Invalid path segment") +			} +		} +  		switch value := value.(type) {  		case walk.NullScalar:  			writer.writer.WriteString("null") @@ -124,66 +139,143 @@ func (writer *JSONWriter) write(targetPath []walk.Value, value walk.Value) error  	}  	afterValue: { -		if len(writer.path) == 0 { -			writer.writer.WriteRune('\n') -			goto beforeValue -		} -		switch writer.path[len(writer.path) - 1].(type) { -		case walk.NumberScalar: -			// TODO: second part of this condition might be redundant -			if len(writer.path) - 1 <= diversionPoint && len(targetPath) >= len(writer.path) && isNumber(targetPath[len(writer.path) - 1]) { -				writer.writer.WriteString(",\n") +		if diversionPoint < len(writer.path) { +			if diversionPoint == len(writer.path) - 1 && diversionPoint < len(targetPath) { +				segment := writer.path[diversionPoint] +				switch segment.(type) { +				case walk.NumberScalar: +					_, isNumber := targetPath[diversionPoint].(walk.NumberScalar) +					if isNumber { +						writer.writer.WriteString(",\n") +						writer.path = writer.path[:diversionPoint] +						goto inArray +					} +				case walk.StringStructure: +					_, isString := targetPath[diversionPoint].(walk.StringStructure) +					if isString { +						writer.writer.WriteString(",\n") +						writer.path = writer.path[:diversionPoint] +						goto inMap +					} +				default: +					panic("Invalid segment type") +				} +			} + +			writer.writer.WriteString("\n") +			switch writer.path[len(writer.path) - 1].(type) { +			case walk.NumberScalar:  				writer.path = writer.path[:len(writer.path) - 1]  				goto inArray -			} else { -				writer.writer.WriteString("\n") -				writer.indent(len(writer.path) - 1) -				writer.writer.WriteString("]") -				writer.path = writer.path[:len(writer.path) - 1] -				goto afterValue -			} -		case walk.StringStructure: -			if len(writer.path) -1 <= diversionPoint && len(targetPath) >= len(writer.path) && isString(targetPath[len(writer.path) - 1]) { -				writer.writer.WriteString(",\n") +			case walk.StringStructure:  				writer.path = writer.path[:len(writer.path) - 1]  				goto inMap -			} else { +			default: +				panic("Invalid segment type") +			} +		} + +		// TODO: handle len(writer.path) == 0 +		if diversionPoint < len(targetPath) { +			if len(writer.path) == 0 {  				writer.writer.WriteString("\n") -				writer.indent(len(writer.path) - 1) -				writer.writer.WriteString("}") -				writer.path = writer.path[:len(writer.path) - 1] -				goto afterValue +				goto beforeValue +			} +			segment := writer.path[diversionPoint - 1] +			writer.writer.WriteString(",") +			diversionPoint-- +			writer.path = writer.path[:diversionPoint] +			switch segment.(type) { +			case walk.NumberScalar: +				goto inArray +			case walk.StringStructure: +				goto inMap +			default: +				panic("Invalid segment type")  			} +		} + +		if len(writer.path) == 0 { +			writer.writer.WriteString("\n") +			goto beforeValue +		} +		segment := writer.path[diversionPoint - 1] +		writer.writer.WriteString(",\n") +		diversionPoint-- +		writer.path = writer.path[:diversionPoint] +		switch segment.(type) { +		case walk.NumberScalar: +			goto inArray +		case walk.StringStructure: +			goto inMap  		default: -			panic("Invalid path segment type") +			panic("Invalid segment type")  		}  	} -	inMap: { -		if len(writer.path) <= diversionPoint && len(targetPath) > len(writer.path) && isString(targetPath[len(writer.path)]) { -			writer.indent(len(writer.path) + 1) -			writer.writer.WriteString(fmt.Sprintf("%q: ", targetPath[len(writer.path)].(walk.StringStructure))) -			writer.path = append(writer.path, targetPath[len(writer.path)].(walk.StringStructure)) -			goto beforeValue -		} else { -			writer.writer.WriteString("\n}") +	inArray: { +		if diversionPoint < len(writer.path) { +			writer.indent(len(writer.path)) +			writer.writer.WriteString("]")  			goto afterValue  		} + +		if diversionPoint < len(targetPath) { +			switch s := targetPath[diversionPoint].(type) { +			case walk.NumberScalar: +				writer.path = append(writer.path, s) +				diversionPoint++ +				writer.indent(len(writer.path)) +				goto beforeValue +			case walk.StringStructure: +				writer.indent(len(writer.path)) +				writer.writer.WriteString("]") +				goto afterValue +			default: +				panic("Invalid segment type") +			} +		} + +		writer.indent(len(writer.path)) +		writer.writer.WriteString("]") +		goto afterValue  	} -	inArray: { -		if len(writer.path) <= diversionPoint && len(targetPath) > len(writer.path) && isNumber(targetPath[len(writer.path)]) { -			writer.indent(len(writer.path) + 1) -			writer.path = append(writer.path, walk.NumberScalar(0)) -			goto beforeValue -		} else { -			writer.writer.WriteString("\n]") +	inMap: { +		if diversionPoint < len(writer.path) { +			writer.indent(len(writer.path)) +			writer.writer.WriteString("}")  			goto afterValue  		} + +		if diversionPoint < len(targetPath) { +			switch s := targetPath[diversionPoint].(type) { +			case walk.NumberScalar: +				writer.indent(len(writer.path)) +				writer.writer.WriteString("}") +				goto afterValue +			case walk.StringStructure: +				writer.path = append(writer.path, s) +				diversionPoint++ +				writer.indent(len(writer.path)) +				writer.writer.WriteString(fmt.Sprintf("%q: ", s)) +				goto beforeValue +			} +		} + +		writer.indent(len(writer.path)) +		writer.writer.WriteString("}") +		goto afterValue  	}  }  func (writer *JSONWriter) AssertDone() { +	switch writer.state { +	case JSONWriterStateInArray: +		writer.writer.WriteString("]") +	case JSONWriterStateInMap: +		writer.writer.WriteString("}") +	}  	for i := len(writer.path) - 1; i >= 0; i -= 1 {  		switch writer.path[i].(type) {  		case walk.NumberScalar: | 
