Skip to content

Commit

Permalink
Merge pull request #23 from tdakkota/fix/folded-scalar-emit
Browse files Browse the repository at this point in the history
fix: emit break after folded scalar start
  • Loading branch information
tdakkota authored Aug 11, 2022
2 parents 1a6cf3a + 1298894 commit cc8887c
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 57 deletions.
23 changes: 11 additions & 12 deletions emitterc.go
Original file line number Diff line number Diff line change
Expand Up @@ -1835,7 +1835,7 @@ func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []by
}

func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool {
if is_space(value, 0) || is_break(value, 0) {
if len(value) > 0 && (is_space(value, 0) || is_break(value, 0)) {
indent_hint := []byte{'0' + byte(emitter.best_indent)}
if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) {
return false
Expand Down Expand Up @@ -1926,29 +1926,28 @@ func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) boo
if !yaml_emitter_write_block_scalar_hints(emitter, value) {
return false
}
no_comment := len(emitter.line_comment) == 0
if !yaml_emitter_process_line_comment(emitter) {
return false
}

if no_comment {
if !put_break(emitter) {
return false
}
}
// emitter.indention = true
emitter.whitespace = true

breaks := true
leading_spaces := true
for i := 0; i < len(value); {
if is_break(value, i) {
if !breaks && !leading_spaces && value[i] == '\n' {
k := 0
for is_break(value, k) {
if !breaks && !leading_spaces {
k := i
for k < len(value) && is_break(value, k) {
k += width(value[k])
}
// FIXME(tdakkota): hacky, probably there is a better way to do this
//
// Do not break the line if the next line is additionally indented.
//
// It leads to double line breaking.
next_line_more_indent := bytes.HasPrefix(value[i+1:], []byte{' '})
if !is_blankz(value, k) && !next_line_more_indent {
if k < len(value) && !is_blank(value, k) {
if !put_break(emitter) {
return false
}
Expand Down
149 changes: 104 additions & 45 deletions encode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"fmt"
"math"
"net"
"reflect"
"strconv"
"strings"
"testing"
Expand Down Expand Up @@ -928,63 +929,121 @@ func newTime(t time.Time) *time.Time {
}

func testEncodeDecodeString(t *testing.T, input string) {
t.Run("Scalar", func(t *testing.T) {
defer func() {
t.Logf("Input: %q", input)
}()
a := require.New(t)

data, err := yaml.Marshal(input)
a.NoError(err)
t.Run("String", func(t *testing.T) {
tests := []struct {
name string
input interface{}
}{
{
"Scalar",
input,
},
{
"Mapping",
map[string]string{"foo": input},
},
{
"Sequence",
[]string{input},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
defer func() {
t.Logf("Input: %#v", tt.input)
}()
a := require.New(t)

defer func() {
t.Logf("Marshal: %q", data)
}()
data, err := yaml.Marshal(tt.input)
a.NoError(err)

var output string
a.NoError(yaml.Unmarshal(data, &output))
a.Equal(input, output)
})
t.Run("Mapping", func(t *testing.T) {
defer func() {
t.Logf("Input: %q", input)
}()
a := require.New(t)

input := map[string]string{"foo": input}
data, err := yaml.Marshal(input)
a.NoError(err)
defer func() {
t.Logf("Marshal: %q", data)
}()

defer func() {
t.Logf("Marshal: %q", data)
}()
typ := reflect.TypeOf(tt.input)
target := reflect.New(typ)
a.NoError(yaml.Unmarshal(data, target.Interface()))

var output map[string]string
a.NoError(yaml.Unmarshal(data, &output))
a.Equal(input, output)
output := target.Elem().Interface()
a.Equal(tt.input, output)
})
}
})
t.Run("Sequence", func(t *testing.T) {
defer func() {
t.Logf("Input: %q", input)
}()
a := require.New(t)

input := []string{input}
data, err := yaml.Marshal(input)
a.NoError(err)
t.Run("Node", func(t *testing.T) {
for _, style := range []yaml.Style{
0,
yaml.DoubleQuotedStyle,
yaml.SingleQuotedStyle,
yaml.LiteralStyle,
yaml.FoldedStyle,
} {
tt := struct {
input yaml.Node
}{
input: yaml.Node{
Kind: yaml.ScalarNode,
Style: style,
Value: input,
},
}
t.Run(fmt.Sprintf("%sStyle", style), func(t *testing.T) {
defer func() {
t.Logf("Input: %#v", tt.input)
}()
a := require.New(t)

defer func() {
t.Logf("Marshal: %q", data)
}()
data, err := yaml.Marshal(tt.input)
a.NoError(err)

var output []string
a.NoError(yaml.Unmarshal(data, &output))
a.Equal(input, output)
defer func() {
t.Logf("Marshal: %q", data)
}()

var output yaml.Node
a.NoError(yaml.Unmarshal(data, &output))
if output.Kind == yaml.DocumentNode {
output = *output.Content[0]
}
a.Equal(tt.input.Value, output.Value)
})
}
})
}

func TestEncodeDecodeString(t *testing.T) {
for i, tt := range []string{
"",
" ",
"\t",
"\n",
"\r",
"\u0085",
"\u2028",
"\u2029",
"\"",
":",
"?",
"#",

"foo",
"foo\n",
"\nfoo",
"\n\nfoo",
"\n\tfoo",
"\tfoo",
" foo",
"# foo",
"\n# foo",
"foo\"",
"- foo\n - bar\n",
"\n- foo\n - bar\n",

"0\n0",
"0\n\n0",
"0\n\n\n0",

"\t\ndetected\n",
"\tB\n\tC\n",

Expand Down
23 changes: 23 additions & 0 deletions node.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package yaml

import (
"fmt"
"strings"
"unicode/utf8"
)
Expand Down Expand Up @@ -28,6 +29,28 @@ const (
FlowStyle
)

// String implements fmt.Stringer.
func (s Style) String() string {
switch s {
case 0:
return "Undefined"
case TaggedStyle:
return "Tagged"
case DoubleQuotedStyle:
return "DoubleQuoted"
case SingleQuotedStyle:
return "SingleQuoted"
case LiteralStyle:
return "Literal"
case FoldedStyle:
return "Folded"
case FlowStyle:
return "Flow"
default:
return fmt.Sprintf("Style(%d)", s)
}
}

// Node represents an element in the YAML document hierarchy. While documents
// are typically encoded and decoded into higher level types, such as structs
// and maps, Node is an intermediate representation that allows detailed
Expand Down
19 changes: 19 additions & 0 deletions node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2884,3 +2884,22 @@ func fprintCommentSet(out io.Writer, node *yaml.Node) {
fmt.Fprintf(out, "%q / %q / %q", node.HeadComment, node.LineComment, node.FootComment)
}
}

func TestStyle_String(t *testing.T) {
a := require.New(t)
for _, tc := range []struct {
style yaml.Style
expect string
}{
{0, "Undefined"},
{yaml.TaggedStyle, "Tagged"},
{yaml.DoubleQuotedStyle, "DoubleQuoted"},
{yaml.SingleQuotedStyle, "SingleQuoted"},
{yaml.LiteralStyle, "Literal"},
{yaml.FoldedStyle, "Folded"},
{yaml.FlowStyle, "Flow"},
{4421412, "Style(4421412)"},
} {
a.Equal(tc.expect, tc.style.String())
}
}

0 comments on commit cc8887c

Please sign in to comment.