Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs/???: Using compiled CUE to "glue" together bits of data #172

Open
jpluscplusm opened this issue Jul 26, 2024 · 1 comment
Open

docs/???: Using compiled CUE to "glue" together bits of data #172

jpluscplusm opened this issue Jul 26, 2024 · 1 comment
Labels
content idea Idea for a new piece of content triage Triage required by the CUE team

Comments

@jpluscplusm
Copy link
Collaborator

Slack thread: https://cuelang.slack.com/archives/CLT3ULF6C/p1716865650006559

Thread content

OP

my expectation was that fill path would do unification .. i am starting to think that i am missing something about escaping that string but not sure.

package main

import (
	"fmt"
	"testing"
)

func lokkupPath(value cue.Value, path string) (cue.Value, error) {
	var val cue.Value
	fieldValue := value.LookupPath(cue.ParsePath(path))
	if !fieldValue.Exists() || fieldValue.Kind() == cue.BottomKind {
		return val, ErrInvalidReference
	}
	return fieldValue, nil
}

func TestFillPath(t *testing.T) {
	tmap := map[string]any{
		"xx": "\\(Ref.Val)/xx",
		"yy": "\\(Ref.Val)/yy",
	}

	cctx := cuecontext.New()
	code := cctx.Encode(tmap)
	// fmt.Println(code)

	codeval := code.FillPath(cue.ParsePath("Ref"), struct {
		Val string
	}{
		Val: "test",
	})

	// fmt.Println(codeval)

	xx, err := lokkupPath(codeval, "xx")
	if err != nil {
		t.Errorf("failed")
	}

	fmt.Println("xx", xx)

}

// ---- output
// xx "\\(Ref.Val)/xx"
// PASS

Reply

I think what you are actually after is CompileString. At least I hope the following example makes the distinction between cue.Context.Encode and cue.Context.CompileString clear

go mod tidy
go run .
cmp stdout stdout.golden

-- go.mod --
module mod.example

go 1.22.3

require cuelang.org/go v0.9.0

-- main.go --
package main

import (
	"fmt"

	"cuelang.org/go/cue/cuecontext"
)

func main() {
	ctx := cuecontext.New()

	tmap := map[string]any{
		"Ref": struct {
			Val string
		}{
			Val: "test",
		},
	}

	// Use cue.Context.Encode to convert a Go value to
	// CUE data. Note that the Go value can contain
	// cue.Value values.
	tmapValue := ctx.Encode(tmap)

	// Use cue.Context.CompileString to compile some CUE
	derived := ctx.CompileString(`
		Ref: _
		x: "\(Ref.Val)/gg"
	`)

	// Use cue.Value.Unify to unify
	res := tmapValue.Unify(derived)
	fmt.Printf("%v\n", res)
}
-- stdout.golden --
{
	Ref: {
		Val: "test"
	}
	x: "test/gg"
}

If you use cue.Context.Encode on a Go value, then the resulting cue.Value will be just data

Hence your expectation of a reference ("(Ref.Val)") resolving is not correct.

But as you can see, you can use a combination of various techniques to give you a variety of cue.Value's, and "glue" them together using cue.Value.Unify

@jpluscplusm jpluscplusm added content idea Idea for a new piece of content triage Triage required by the CUE team labels Jul 26, 2024
@rogpeppe
Copy link
Member

Alternative version using FillPath:

go mod tidy
go run .
cmp stdout stdout.golden

-- go.mod --
module mod.example

go 1.22.3

require cuelang.org/go v0.9.0

-- main.go --
package main

import (
	"fmt"

	"cuelang.org/go/cue"
	"cuelang.org/go/cue/cuecontext"
)

func main() {
	ctx := cuecontext.New()

	v := ctx.CompileString(`
		Ref!: _
		x: "\(Ref.Val)/gg"
	`)
	v = v.FillPath(cue.MakePath(cue.Str("Ref")), map[string]string{"Val": "test"})
	fmt.Printf("%v\n", v)
}
-- stdout.golden --
{
	Ref: {
		Val: "test"
	}
	x: "test/gg"
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
content idea Idea for a new piece of content triage Triage required by the CUE team
Projects
Status: Backlog
Development

No branches or pull requests

2 participants