cue get go
CUE v0.18.0
add Go dependencies to the current module
Usage
cue get go [flags] [packages]go converts Go types into CUE definitions
The command "cue get go" is like "go get", but converts the retrieved Go packages to CUE. The retrieved packages are put in the CUE module's pkg directory at the import path of the corresponding Go package. The converted definitions are available to any CUE file within the CUE module by using this import path.
The Go type definitions are converted to CUE based on how they would be interpreted by Go's encoding/json package. Definitions for a Go file foo.go are written to a CUE file named foo_go_gen.cue.
It is safe for users to add additional files to the generated directories, as long as their name does not end with _gen.*.
Rules of Converting Go types to CUE
Go structs are converted to cue structs adhering to the following conventions:
- field names are translated based on the definition of a "json" or "yaml"
tag, in that order. A --codec flag can be used to change the priority of
the tag search. - the tag found for a field also decides how it is encoded: the field
is optional if the tag has an "omitempty" or "omitzero" option, and
a pointer field is not nullable if it is a "toml" tag, as TOML has no
null. Fields without any such tag follow the first codec. - embedded structs marked with a json inline tag unify with struct
definition. For instance, the Go struct struct MyStruct {
Common json:",inline"
Field string
} translates to the CUE struct #MyStruct: Common & {
Field: string
} - a type that implements MarshalJSON, UnmarshalJSON, MarshalYAML, or
UnmarshalYAML is translated to top (_) to indicate it may be any
value. For some Go core types for which the implementation of these
methods is known, like time.Time, the type may be more specific. - a type implementing MarshalText or UnmarshalText is represented as
the CUE type string - slices and arrays convert to CUE lists, except when the element type is
byte, in which case it translates to the CUE bytes type.
In the case of arrays, the length of the CUE value is constrained
accordingly, when possible. - Maps translate to a CUE struct, where all elements are constrained to
be of Go map element type. Like for JSON, map keys must be strings,
integers, or types implementing MarshalText or UnmarshalText, and are
all translated to string labels. - Pointers translate to a sum type with the default value of null and
the Go type as an alternative value. - Field tags are translated to CUE's field attributes. In some cases,
the contents are rewritten to reflect the corresponding types in CUE.
The @go attribute is added if the field name or type definition differs
between the generated CUE and the original Go.Native CUE Constraints
Native CUE constraints may be defined in separate cue files alongside the generated files either in the original Go directory or in the generated directory. These files can impose additional constraints on types and values that are not otherwise expressible in Go. The package name for these CUE files must be the same as that of the Go package.
For instance, for the type
package foo type IP4String stringdefined in the Go package, one could add a cue file foo.cue with the following contents to allow IP4String to assume only valid IP4 addresses:
package foo // IP4String defines a valid IP4 address.
#IP4String: =~#"^\#(byte)\.\#(byte)\.\#(byte)\.\#(byte)$"# // byte defines string allowing integer values of 0-255.
byte = #"([01]?\d?\d|2[0-4]\d|25[0-5])"#The "cue get go" command copies any cue files in the original Go package directory that has a package clause with the same name as the Go package to the destination directory, replacing its .cue ending with _gen.cue.
Alternatively, the additional native constraints can be added to the generated package, as long as the file name does not end with _gen.cue. Running cue get go again to regenerate the package will never overwrite any files not ending with _gen.*.
Constants and Enums
Go does not have an enum or sum type. Conventionally, a type that is supposed to be an enum is followed by a const block with the allowed values for that type. However, as that is only a guideline and not a hard rule, these cases cannot be translated to CUE disjunctions automatically.
Constant values, however, are generated in a way that makes it easy to convert a type to a proper enum using native CUE constraints. For instance, the Go type
package foo type Switch int const (
Off Switch = iota
On
)translates into the following CUE definitions:
package foo #Switch: int // #enumSwitch #enumSwitch: Off | On Off: 0
On: 1This definition allows any integer value for #Switch, while the #enumSwitch value defines all defined constants for Switch and thus all valid values if #Switch were to be interpreted as an enum type. To turn #Switch into an enum, include the following constraint in, say, enum.cue, in either the original source directory or the generated directory:
package foo // limit the valid values for Switch to those existing as constants with
// the same type.
#Switch: #enumSwitchThis tells CUE that only the values enumerated by #enumSwitch are valid values for #Switch. Note that there are now two definitions of #Switch. CUE handles this in the usual way by unifying the two definitions, in which case the more restrictive enum interpretation of #Switch remains.
Flags
--codec string comma-separated priority list of struct tags to use for field names
-e, --exclude string comma-separated list of regexps of identifiers to omit
--local generates files in the main module locally
--outfile string generate one CUE file for a single Go package
-p, --package string package name for generated CUE files
-v, --verbose print information about progressGlobal flags
-E, --all-errors print all available errors
-C, --chdir string change working directory before running command (must be the first flag)
-i, --ignore proceed in the presence of errors
-s, --simplify simplify output