This commit is contained in:
Mike Farah 2023-04-08 19:56:35 +10:00
parent 52b364ec52
commit 66ab916c6b
14 changed files with 92 additions and 111 deletions

View File

@ -12,7 +12,6 @@ import (
"unicode"
"golang.org/x/net/html/charset"
yaml "gopkg.in/yaml.v3"
)
type xmlDecoder struct {
@ -36,8 +35,8 @@ func (dec *xmlDecoder) Init(reader io.Reader) error {
return nil
}
func (dec *xmlDecoder) createSequence(nodes []*xmlNode) (*yaml.Node, error) {
yamlNode := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
func (dec *xmlDecoder) createSequence(nodes []*xmlNode) (*CandidateNode, error) {
yamlNode := &CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
for _, child := range nodes {
yamlChild, err := dec.convertToYamlNode(child)
if err != nil {
@ -64,9 +63,9 @@ func (dec *xmlDecoder) processComment(c string) string {
return replacement
}
func (dec *xmlDecoder) createMap(n *xmlNode) (*yaml.Node, error) {
func (dec *xmlDecoder) createMap(n *xmlNode) (*CandidateNode, error) {
log.Debug("createMap: headC: %v, lineC: %v, footC: %v", n.HeadComment, n.LineComment, n.FootComment)
yamlNode := &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map"}
yamlNode := &CandidateNode{Kind: MappingNode, Tag: "!!map"}
if len(n.Data) > 0 {
log.Debugf("creating content node for map: %v", dec.prefs.ContentName)
@ -82,7 +81,7 @@ func (dec *xmlDecoder) createMap(n *xmlNode) (*yaml.Node, error) {
label := keyValuePair.K
children := keyValuePair.V
labelNode := createScalarNode(label, label)
var valueNode *yaml.Node
var valueNode *CandidateNode
var err error
if i == 0 {
@ -126,26 +125,26 @@ func (dec *xmlDecoder) createMap(n *xmlNode) (*yaml.Node, error) {
return yamlNode, nil
}
func (dec *xmlDecoder) createValueNodeFromData(values []string) *yaml.Node {
func (dec *xmlDecoder) createValueNodeFromData(values []string) *CandidateNode {
switch len(values) {
case 0:
return createScalarNode(nil, "")
case 1:
return createScalarNode(values[0], values[0])
default:
content := make([]*yaml.Node, 0)
content := make([]*CandidateNode, 0)
for _, value := range values {
content = append(content, createScalarNode(value, value))
}
return &yaml.Node{
Kind: yaml.SequenceNode,
return &CandidateNode{
Kind: SequenceNode,
Tag: "!!seq",
Content: content,
}
}
}
func (dec *xmlDecoder) convertToYamlNode(n *xmlNode) (*yaml.Node, error) {
func (dec *xmlDecoder) convertToYamlNode(n *xmlNode) (*CandidateNode, error) {
if len(n.Children) > 0 {
return dec.createMap(n)
}
@ -190,10 +189,8 @@ func (dec *xmlDecoder) Decode() (*CandidateNode, error) {
dec.finished = true
return &CandidateNode{
Node: &yaml.Node{
Kind: yaml.DocumentNode,
Content: []*yaml.Node{firstNode},
},
Kind: DocumentNode,
Content: []*CandidateNode{firstNode},
}, nil
}

View File

@ -2,20 +2,18 @@ package yqlib
import (
"io"
yaml "gopkg.in/yaml.v3"
)
type Encoder interface {
Encode(writer io.Writer, node *yaml.Node) error
Encode(writer io.Writer, node *CandidateNode) error
PrintDocumentSeparator(writer io.Writer) error
PrintLeadingContent(writer io.Writer, content string) error
CanHandleAliases() bool
}
func mapKeysToStrings(node *yaml.Node) {
func mapKeysToStrings(node *CandidateNode) {
if node.Kind == yaml.MappingNode {
if node.Kind == MappingNode {
for index, child := range node.Content {
if index%2 == 0 { // its a map key
child.Tag = "!!str"

View File

@ -4,8 +4,6 @@ import (
"encoding/base64"
"fmt"
"io"
yaml "gopkg.in/yaml.v3"
)
type base64Encoder struct {
@ -28,9 +26,9 @@ func (e *base64Encoder) PrintLeadingContent(writer io.Writer, content string) er
return nil
}
func (e *base64Encoder) Encode(writer io.Writer, originalNode *yaml.Node) error {
node := unwrapDoc(originalNode)
if guessTagFromCustomType(node) != "!!str" {
func (e *base64Encoder) Encode(writer io.Writer, originalNode *CandidateNode) error {
node := originalNode.unwrapDocument()
if node.guessTagFromCustomType() != "!!str" {
return fmt.Errorf("cannot encode %v as base64, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag)
}
_, err := writer.Write([]byte(e.encoding.EncodeToString([]byte(originalNode.Value))))

View File

@ -4,8 +4,6 @@ import (
"encoding/csv"
"fmt"
"io"
yaml "gopkg.in/yaml.v3"
)
type csvEncoder struct {
@ -89,7 +87,7 @@ func (e *csvEncoder) encodeObjects(csvWriter *csv.Writer, content []*CandidateNo
}
for i, child := range content {
if child.Kind != yaml.MappingNode {
if child.Kind != MappingNode {
return fmt.Errorf("csv object encoding only works for arrays of flat objects (string key => string/numbers/boolean value), child[%v] is a %v", i, child.Tag)
}
row := e.createChildRow(child, headers)
@ -103,7 +101,7 @@ func (e *csvEncoder) encodeObjects(csvWriter *csv.Writer, content []*CandidateNo
}
func (e *csvEncoder) Encode(writer io.Writer, originalNode *CandidateNode) error {
if originalNode.Kind == yaml.ScalarNode {
if originalNode.Kind == ScalarNode {
return writeString(writer, originalNode.Value+"\n")
}
@ -111,17 +109,17 @@ func (e *csvEncoder) Encode(writer io.Writer, originalNode *CandidateNode) error
csvWriter.Comma = e.separator
// node must be a sequence
node := unwrapDoc(originalNode)
if node.Kind != yaml.SequenceNode {
node := originalNode.unwrapDocument()
if node.Kind != SequenceNode {
return fmt.Errorf("csv encoding only works for arrays, got: %v", node.Tag)
} else if len(node.Content) == 0 {
return nil
}
if node.Content[0].Kind == yaml.ScalarNode {
if node.Content[0].Kind == ScalarNode {
return e.encodeRow(csvWriter, node.Content)
}
if node.Content[0].Kind == yaml.MappingNode {
if node.Content[0].Kind == MappingNode {
return e.encodeObjects(csvWriter, node.Content)
}

View File

@ -7,7 +7,6 @@ import (
"io"
"github.com/goccy/go-json"
yaml "gopkg.in/yaml.v3"
)
type jsonEncoder struct {
@ -38,9 +37,9 @@ func (je *jsonEncoder) PrintLeadingContent(writer io.Writer, content string) err
return nil
}
func (je *jsonEncoder) Encode(writer io.Writer, node *yaml.Node) error {
func (je *jsonEncoder) Encode(writer io.Writer, node *CandidateNode) error {
if node.Kind == yaml.ScalarNode && je.UnwrapScalar {
if node.Kind == ScalarNode && je.UnwrapScalar {
return writeString(writer, node.Value+"\n")
}
@ -58,6 +57,7 @@ func (je *jsonEncoder) Encode(writer io.Writer, node *yaml.Node) error {
// firstly, convert all map keys to strings
mapKeysToStrings(node)
errorDecoding := node.Decode(&dataBucket)
if errorDecoding != nil {
return errorDecoding
}

View File

@ -8,7 +8,6 @@ import (
"strings"
"github.com/magiconair/properties"
yaml "gopkg.in/yaml.v3"
)
type propertiesEncoder struct {
@ -62,9 +61,9 @@ func (pe *propertiesEncoder) PrintLeadingContent(writer io.Writer, content strin
return nil
}
func (pe *propertiesEncoder) Encode(writer io.Writer, node *yaml.Node) error {
func (pe *propertiesEncoder) Encode(writer io.Writer, node *CandidateNode) error {
if node.Kind == yaml.ScalarNode {
if node.Kind == ScalarNode {
return writeString(writer, node.Value+"\n")
}
@ -79,7 +78,7 @@ func (pe *propertiesEncoder) Encode(writer io.Writer, node *yaml.Node) error {
return err
}
func (pe *propertiesEncoder) doEncode(p *properties.Properties, node *yaml.Node, path string, keyNode *yaml.Node) error {
func (pe *propertiesEncoder) doEncode(p *properties.Properties, node *CandidateNode, path string, keyNode *CandidateNode) error {
comments := ""
if keyNode != nil {
@ -91,7 +90,7 @@ func (pe *propertiesEncoder) doEncode(p *properties.Properties, node *yaml.Node,
p.SetComments(path, strings.Split(commentsWithSpaces, "\n"))
switch node.Kind {
case yaml.ScalarNode:
case ScalarNode:
var nodeValue string
if pe.unwrapScalar || !strings.Contains(node.Value, " ") {
nodeValue = node.Value
@ -100,13 +99,13 @@ func (pe *propertiesEncoder) doEncode(p *properties.Properties, node *yaml.Node,
}
_, _, err := p.Set(path, nodeValue)
return err
case yaml.DocumentNode:
case DocumentNode:
return pe.doEncode(p, node.Content[0], path, node)
case yaml.SequenceNode:
case SequenceNode:
return pe.encodeArray(p, node.Content, path)
case yaml.MappingNode:
case MappingNode:
return pe.encodeMap(p, node.Content, path)
case yaml.AliasNode:
case AliasNode:
return pe.doEncode(p, node.Alias, path, nil)
default:
return fmt.Errorf("Unsupported node %v", node.Tag)
@ -120,7 +119,7 @@ func (pe *propertiesEncoder) appendPath(path string, key interface{}) string {
return fmt.Sprintf("%v.%v", path, key)
}
func (pe *propertiesEncoder) encodeArray(p *properties.Properties, kids []*yaml.Node, path string) error {
func (pe *propertiesEncoder) encodeArray(p *properties.Properties, kids []*CandidateNode, path string) error {
for index, child := range kids {
err := pe.doEncode(p, child, pe.appendPath(path, index), nil)
if err != nil {
@ -130,7 +129,7 @@ func (pe *propertiesEncoder) encodeArray(p *properties.Properties, kids []*yaml.
return nil
}
func (pe *propertiesEncoder) encodeMap(p *properties.Properties, kids []*yaml.Node, path string) error {
func (pe *propertiesEncoder) encodeMap(p *properties.Properties, kids []*CandidateNode, path string) error {
for index := 0; index < len(kids); index = index + 2 {
key := kids[index]
value := kids[index+1]

View File

@ -5,8 +5,6 @@ import (
"io"
"regexp"
"strings"
yaml "gopkg.in/yaml.v3"
)
var unsafeChars = regexp.MustCompile(`[^\w@%+=:,./-]`)
@ -31,9 +29,9 @@ func (e *shEncoder) PrintLeadingContent(writer io.Writer, content string) error
return nil
}
func (e *shEncoder) Encode(writer io.Writer, originalNode *yaml.Node) error {
node := unwrapDoc(originalNode)
if guessTagFromCustomType(node) != "!!str" {
func (e *shEncoder) Encode(writer io.Writer, originalNode *CandidateNode) error {
node := originalNode.unwrapDocument()
if node.guessTagFromCustomType() != "!!str" {
return fmt.Errorf("cannot encode %v as URI, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag)
}

View File

@ -3,8 +3,6 @@ package yqlib
import (
"fmt"
"io"
yaml "gopkg.in/yaml.v3"
)
type tomlEncoder struct {
@ -14,8 +12,8 @@ func NewTomlEncoder() Encoder {
return &tomlEncoder{}
}
func (te *tomlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
if node.Kind == yaml.ScalarNode {
func (te *tomlEncoder) Encode(writer io.Writer, node *CandidateNode) error {
if node.Kind == ScalarNode {
return writeString(writer, node.Value+"\n")
}
return fmt.Errorf("only scalars (e.g. strings, numbers, booleans) are supported for TOML output at the moment. Please use yaml output format (-oy) until the encoder has been fully implemented")

View File

@ -4,8 +4,6 @@ import (
"fmt"
"io"
"net/url"
yaml "gopkg.in/yaml.v3"
)
type uriEncoder struct {
@ -27,9 +25,9 @@ func (e *uriEncoder) PrintLeadingContent(writer io.Writer, content string) error
return nil
}
func (e *uriEncoder) Encode(writer io.Writer, originalNode *yaml.Node) error {
node := unwrapDoc(originalNode)
if guessTagFromCustomType(node) != "!!str" {
func (e *uriEncoder) Encode(writer io.Writer, originalNode *CandidateNode) error {
node := originalNode.unwrapDocument()
if node.guessTagFromCustomType() != "!!str" {
return fmt.Errorf("cannot encode %v as URI, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag)
}
_, err := writer.Write([]byte(url.QueryEscape(originalNode.Value)))

View File

@ -8,8 +8,6 @@ import (
"io"
"regexp"
"strings"
yaml "gopkg.in/yaml.v3"
)
type xmlEncoder struct {
@ -41,14 +39,14 @@ func (e *xmlEncoder) PrintLeadingContent(writer io.Writer, content string) error
return nil
}
func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
func (e *xmlEncoder) Encode(writer io.Writer, node *CandidateNode) error {
encoder := xml.NewEncoder(writer)
// hack so we can manually add newlines to procInst and directives
e.writer = writer
encoder.Indent("", e.indentString)
var newLine xml.CharData = []byte("\n")
mapNode := unwrapDoc(node)
mapNode := node.unwrapDocument()
if mapNode.Tag == "!!map" {
// make sure <?xml .. ?> processing instructions are encoded first
for i := 0; i < len(mapNode.Content); i += 2 {
@ -82,18 +80,18 @@ func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
}
switch node.Kind {
case yaml.MappingNode:
case MappingNode:
err := e.encodeTopLevelMap(encoder, node)
if err != nil {
return err
}
case yaml.DocumentNode:
case DocumentNode:
err := e.encodeComment(encoder, headAndLineComment(node))
if err != nil {
return err
}
unwrappedNode := unwrapDoc(node)
if unwrappedNode.Kind != yaml.MappingNode {
unwrappedNode := node.unwrapDocument()
if unwrappedNode.Kind != MappingNode {
return fmt.Errorf("cannot encode %v to XML - only maps can be encoded", unwrappedNode.Tag)
}
err = e.encodeTopLevelMap(encoder, unwrappedNode)
@ -104,7 +102,7 @@ func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
if err != nil {
return err
}
case yaml.ScalarNode:
case ScalarNode:
var charData xml.CharData = []byte(node.Value)
err := encoder.EncodeToken(charData)
if err != nil {
@ -119,7 +117,7 @@ func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
}
func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *yaml.Node) error {
func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *CandidateNode) error {
err := e.encodeComment(encoder, headAndLineComment(node))
if err != nil {
return err
@ -178,7 +176,7 @@ func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *yaml.Node) er
return e.encodeComment(encoder, footComment(node))
}
func (e *xmlEncoder) encodeStart(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error {
func (e *xmlEncoder) encodeStart(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
err := encoder.EncodeToken(start)
if err != nil {
return err
@ -186,7 +184,7 @@ func (e *xmlEncoder) encodeStart(encoder *xml.Encoder, node *yaml.Node, start xm
return e.encodeComment(encoder, headComment(node))
}
func (e *xmlEncoder) encodeEnd(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error {
func (e *xmlEncoder) encodeEnd(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
err := encoder.EncodeToken(start.End())
if err != nil {
return err
@ -194,13 +192,13 @@ func (e *xmlEncoder) encodeEnd(encoder *xml.Encoder, node *yaml.Node, start xml.
return e.encodeComment(encoder, footComment(node))
}
func (e *xmlEncoder) doEncode(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error {
func (e *xmlEncoder) doEncode(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
switch node.Kind {
case yaml.MappingNode:
case MappingNode:
return e.encodeMap(encoder, node, start)
case yaml.SequenceNode:
case SequenceNode:
return e.encodeArray(encoder, node, start)
case yaml.ScalarNode:
case ScalarNode:
err := e.encodeStart(encoder, node, start)
if err != nil {
return err
@ -258,7 +256,7 @@ func (e *xmlEncoder) encodeComment(encoder *xml.Encoder, commentStr string) erro
return nil
}
func (e *xmlEncoder) encodeArray(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error {
func (e *xmlEncoder) encodeArray(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
if err := e.encodeComment(encoder, headAndLineComment(node)); err != nil {
return err
@ -280,7 +278,7 @@ func (e *xmlEncoder) isAttribute(name string) bool {
!strings.HasPrefix(name, e.prefs.ProcInstPrefix)
}
func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error {
func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
log.Debug("its a map")
//first find all the attributes and put them on the start token
@ -289,7 +287,7 @@ func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *yaml.Node, start xml.
value := node.Content[i+1]
if e.isAttribute(key.Value) {
if value.Kind == yaml.ScalarNode {
if value.Kind == ScalarNode {
attributeName := strings.Replace(key.Value, e.prefs.AttributePrefix, "", 1)
start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{Local: attributeName}, Value: value.Value})
} else {

View File

@ -73,9 +73,9 @@ func (ye *yamlEncoder) PrintLeadingContent(writer io.Writer, content string) err
return nil
}
func (ye *yamlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
func (ye *yamlEncoder) Encode(writer io.Writer, node *CandidateNode) error {
if node.Kind == yaml.ScalarNode && ye.prefs.UnwrapScalar {
if node.Kind == ScalarNode && ye.prefs.UnwrapScalar {
return writeString(writer, node.Value+"\n")
}

View File

@ -189,7 +189,7 @@ type Operation struct {
UpdateAssign bool // used for assign ops, when true it means we evaluate the rhs given the lhs
}
func recurseNodeArrayEqual(lhs *yaml.Node, rhs *yaml.Node) bool {
func recurseNodeArrayEqual(lhs *CandidateNode, rhs *CandidateNode) bool {
if len(lhs.Content) != len(rhs.Content) {
return false
}
@ -283,17 +283,17 @@ func parseSnippet(value string) (*CandidateNode, error) {
return result, err
}
func recursiveNodeEqual(lhs *yaml.Node, rhs *yaml.Node) bool {
func recursiveNodeEqual(lhs *CandidateNode, rhs *CandidateNode) bool {
if lhs.Kind != rhs.Kind {
return false
}
if lhs.Kind == yaml.ScalarNode {
if lhs.Kind == ScalarNode {
//process custom tags of scalar nodes.
//dont worry about matching tags of maps or arrays.
lhsTag := guessTagFromCustomType(lhs)
rhsTag := guessTagFromCustomType(rhs)
lhsTag := lhs.guessTagFromCustomType()
rhsTag := rhs.guessTagFromCustomType()
if lhsTag != rhsTag {
return false
@ -303,11 +303,11 @@ func recursiveNodeEqual(lhs *yaml.Node, rhs *yaml.Node) bool {
if lhs.Tag == "!!null" {
return true
} else if lhs.Kind == yaml.ScalarNode {
} else if lhs.Kind == ScalarNode {
return lhs.Value == rhs.Value
} else if lhs.Kind == yaml.SequenceNode {
} else if lhs.Kind == SequenceNode {
return recurseNodeArrayEqual(lhs, rhs)
} else if lhs.Kind == yaml.MappingNode {
} else if lhs.Kind == MappingNode {
return recurseNodeObjectEqual(lhs, rhs)
}
return false
@ -382,19 +382,19 @@ func parseInt(numberString string) (int, error) {
return int(parsed), err
}
func headAndLineComment(node *yaml.Node) string {
func headAndLineComment(node *CandidateNode) string {
return headComment(node) + lineComment(node)
}
func headComment(node *yaml.Node) string {
func headComment(node *CandidateNode) string {
return strings.Replace(node.HeadComment, "#", "", 1)
}
func lineComment(node *yaml.Node) string {
func lineComment(node *CandidateNode) string {
return strings.Replace(node.LineComment, "#", "", 1)
}
func footComment(node *yaml.Node) string {
func footComment(node *CandidateNode) string {
return strings.Replace(node.FootComment, "#", "", 1)
}

View File

@ -115,8 +115,9 @@ func getCommentsOperator(d *dataTreeNavigator, context Context, expressionNode *
comment = startCommentCharaterRegExp.ReplaceAllString(comment, "")
comment = subsequentCommentCharaterRegExp.ReplaceAllString(comment, "\n")
node := &yaml.Node{Kind: yaml.ScalarNode, Value: comment, Tag: "!!str"}
result := candidate.CreateReplacement(node)
result := candidate.CreateReplacement()
result.Kind = ScalarNode
result.Tag = "!!str"
result.LeadingContent = "" // don't include the leading yaml content when retrieving a comment
results.PushBack(result)
}

View File

@ -3,8 +3,6 @@ package yqlib
import (
"fmt"
"strconv"
yaml "gopkg.in/yaml.v3"
)
type compareTypePref struct {
@ -32,27 +30,27 @@ func compare(prefs compareTypePref) func(d *dataTreeNavigator, context Context,
return createBooleanCandidate(lhs, false), nil
}
lhs.Node = unwrapDoc(lhs.Node)
rhs.Node = unwrapDoc(rhs.Node)
lhsU := lhs.unwrapDocument()
rhsU := rhs.unwrapDocument()
switch lhs.Node.Kind {
case yaml.MappingNode:
switch lhsU.Kind {
case MappingNode:
return nil, fmt.Errorf("maps not yet supported for comparison")
case yaml.SequenceNode:
case SequenceNode:
return nil, fmt.Errorf("arrays not yet supported for comparison")
default:
if rhs.Node.Kind != yaml.ScalarNode {
return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhs.Node.Tag, rhs.Path, lhs.Node.Tag)
if rhsU.Kind != ScalarNode {
return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhsU.Tag, rhs.Path, lhsU.Tag)
}
target := lhs.CreateReplacement(&yaml.Node{})
boolV, err := compareScalars(context, prefs, lhs.Node, rhs.Node)
target := lhs.CreateReplacement()
boolV, err := compareScalars(context, prefs, lhsU, rhsU)
return createBooleanCandidate(target, boolV), err
}
}
}
func compareDateTime(layout string, prefs compareTypePref, lhs *yaml.Node, rhs *yaml.Node) (bool, error) {
func compareDateTime(layout string, prefs compareTypePref, lhs *CandidateNode, rhs *CandidateNode) (bool, error) {
lhsTime, err := parseDateTime(layout, lhs.Value)
if err != nil {
return false, err
@ -73,9 +71,9 @@ func compareDateTime(layout string, prefs compareTypePref, lhs *yaml.Node, rhs *
}
func compareScalars(context Context, prefs compareTypePref, lhs *yaml.Node, rhs *yaml.Node) (bool, error) {
lhsTag := guessTagFromCustomType(lhs)
rhsTag := guessTagFromCustomType(rhs)
func compareScalars(context Context, prefs compareTypePref, lhs *CandidateNode, rhs *CandidateNode) (bool, error) {
lhsTag := lhs.guessTagFromCustomType()
rhsTag := rhs.guessTagFromCustomType()
isDateTime := lhs.Tag == "!!timestamp"
// if the lhs is a string, it might be a timestamp in a custom format.