diff --git a/content/docs/tour/types/_en.md b/content/docs/tour/types/_en.md new file mode 100644 index 000000000..b529b78b2 --- /dev/null +++ b/content/docs/tour/types/_en.md @@ -0,0 +1,9 @@ +--- +title: "Types and Values" +--- + +This tour demonstrates the hierarchy of primitive and complex types that CUE +makes available, along with common methods for constraining and combining these +types. + +## Contents diff --git a/content/docs/tour/types/bottom/en.md b/content/docs/tour/types/bottom/en.md new file mode 100644 index 000000000..83f7c4426 --- /dev/null +++ b/content/docs/tour/types/bottom/en.md @@ -0,0 +1,34 @@ +--- +title: "Bottom / Error" +weight: 2 +--- +Specifying duplicate fields with conflicting values results in an error +or bottom. +_Bottom_ is a special value in CUE, denoted `_|_`, that indicates an +error such as conflicting values. +Any error in CUE results in `_|_`. +Logically all errors are equal, although errors may be associated with +metadata such as an error message. + +Note that an error is different from `null`: `null` is a valid value, +whereas `_|_` is not. + +{{{with code "en" "bottom"}}} +exec cue eval -i bottom.cue +cmp stdout '$ cue eval -i bottom.cue' +-- bottom.cue -- +a: 4 +a: 5 + +l: [ 1, 2] +l: [ 1, 3] + +list: [0, 1, 2] +val: list[3] +-- $ cue eval -i bottom.cue -- +a: _|_ // a: conflicting values 5 and 4 +l: [1, _|_, // l.1: conflicting values 3 and 2 +] +list: [0, 1, 2] +val: _|_ // val: index out of range [3] with length 3 +{{{end}}} diff --git a/content/docs/tour/types/bottom/gen_cache.cue b/content/docs/tour/types/bottom/gen_cache.cue new file mode 100644 index 000000000..d96f790af --- /dev/null +++ b/content/docs/tour/types/bottom/gen_cache.cue @@ -0,0 +1,20 @@ +package site +{ + content: { + docs: { + tour: { + types: { + bottom: { + page: { + cache: { + code: { + bottom: "nVWmtoCwxo2MltMzeeFZCXDasDDlZM7LFe6yfnQG1SU=" + } + } + } + } + } + } + } + } +} diff --git a/content/docs/tour/types/bottom/page.cue b/content/docs/tour/types/bottom/page.cue new file mode 100644 index 000000000..87107a377 --- /dev/null +++ b/content/docs/tour/types/bottom/page.cue @@ -0,0 +1,3 @@ +package site + +content: docs: tour: types: bottom: {} diff --git a/content/docs/tour/types/bounddef/en.md b/content/docs/tour/types/bounddef/en.md new file mode 100644 index 000000000..c7afb0ac7 --- /dev/null +++ b/content/docs/tour/types/bounddef/en.md @@ -0,0 +1,43 @@ +--- +title: "Predefined Bounds" +weight: 14 +--- +CUE numbers have arbitrary precision. +Also there is no unsigned integer type. + +CUE defines the following predefined identifiers to restrict the bounds of +integers to common values. + +{{{with code "en" "defined"}}} +-- in.cue -- +uint: >=0 +uint8: >=0 & <=255 +int8: >=-128 & <=127 +uint16: >=0 & <=65536 +int16: >=-32_768 & <=32_767 +rune: >=0 & <=0x10FFFF +uint32: >=0 & <=4_294_967_296 +int32: >=-2_147_483_648 & <=2_147_483_647 +uint64: >=0 & <=18_446_744_073_709_551_615 +int64: >=-9_223_372_036_854_775_808 & <=9_223_372_036_854_775_807 +int128: >=-170_141_183_460_469_231_731_687_303_715_884_105_728 & + <=170_141_183_460_469_231_731_687_303_715_884_105_727 +uint128: >=0 & <=340_282_366_920_938_463_463_374_607_431_768_211_455 +{{{end}}} + +{{{with code "en" "failure"}}} +exec cue eval -ic bound.cue +cmp stdout '$ cue eval -ic bound.cue' +-- bound.cue -- +#positive: uint +#byte: uint8 +#word: int32 + +a: #positive & -1 +b: #byte & 128 +c: #word & 2_000_000_000 +-- $ cue eval -ic bound.cue -- +a: _|_ // a: invalid value -1 (out of bound >=0) +b: 128 +c: 2000000000 +{{{end}}} diff --git a/content/docs/tour/types/bounddef/gen_cache.cue b/content/docs/tour/types/bounddef/gen_cache.cue new file mode 100644 index 000000000..d1c4f96f4 --- /dev/null +++ b/content/docs/tour/types/bounddef/gen_cache.cue @@ -0,0 +1,21 @@ +package site +{ + content: { + docs: { + tour: { + types: { + bounddef: { + page: { + cache: { + code: { + defined: "MohhkFjPJDw6JacZKpy05dq6V7IvtCjcSRoAeVyZzOQ=" + failure: "HvILLQ/uSPtoJEAq/x+mzGPoWMXdigD18sCAU9YwMIg=" + } + } + } + } + } + } + } + } +} diff --git a/content/docs/tour/types/bounddef/page.cue b/content/docs/tour/types/bounddef/page.cue new file mode 100644 index 000000000..89fca800b --- /dev/null +++ b/content/docs/tour/types/bounddef/page.cue @@ -0,0 +1,3 @@ +package site + +content: docs: tour: types: bounddef: {} diff --git a/content/docs/tour/types/bounds/en.md b/content/docs/tour/types/bounds/en.md new file mode 100644 index 000000000..c52e29e68 --- /dev/null +++ b/content/docs/tour/types/bounds/en.md @@ -0,0 +1,39 @@ +--- +title: "Bounds" +weight: 13 +--- +Bounds define a lower bound, upper bound, or inequality for a certain value. +They work on numbers, strings, bytes and null. + +The bound is defined for all values for which the corresponding comparison +operation is defined. +For instance `>5.0` allows all floating point values greater than `5.0`, +whereas `<0` allows all negative numbers (int or float). + + +{{{with code "en" "failure"}}} +exec cue eval -ic bounds.cue +cmp stdout '$ cue eval -ic bounds.cue' +-- bounds.cue -- +#rn: >=3 & <8 // type int | float + +#ri: >=3 & <8 & int // type int + +#rf: >=3 & <=8.0 // type float +#rs: >="a" & <"mo" + +a: #rn & 3.5 +b: #ri & 3.5 +c: #rf & 3 +d: #rs & "ma" +e: #rs & "mu" + +r1: #rn & >=5 & <10 +-- $ cue eval -ic bounds.cue -- +a: 3.5 +b: _|_ // b: conflicting values int and 3.5 (mismatched types int and float) +c: 3 +d: "ma" +e: _|_ // e: invalid value "mu" (out of bound <"mo") +r1: >=5 & <8 +{{{end}}} diff --git a/content/docs/tour/types/bounds/gen_cache.cue b/content/docs/tour/types/bounds/gen_cache.cue new file mode 100644 index 000000000..b01c2497f --- /dev/null +++ b/content/docs/tour/types/bounds/gen_cache.cue @@ -0,0 +1,20 @@ +package site +{ + content: { + docs: { + tour: { + types: { + bounds: { + page: { + cache: { + code: { + failure: "i2XOqSgd0R4pfPqroxbF1GW311kDl7jEuSD1Ax4gNTY=" + } + } + } + } + } + } + } + } +} diff --git a/content/docs/tour/types/bounds/page.cue b/content/docs/tour/types/bounds/page.cue new file mode 100644 index 000000000..16ee31148 --- /dev/null +++ b/content/docs/tour/types/bounds/page.cue @@ -0,0 +1,3 @@ +package site + +content: docs: tour: types: bounds: {} diff --git a/content/docs/tour/types/bytes/en.md b/content/docs/tour/types/bytes/en.md new file mode 100644 index 000000000..841bc4220 --- /dev/null +++ b/content/docs/tour/types/bytes/en.md @@ -0,0 +1,24 @@ +--- +title: "Bytes" +weight: 6 +--- +CUE distinguishes between a `string` and a `bytes` type. +Bytes are converted to base64 when emitting JSON. +Byte literals are defined with single quotes. +The following additional escape sequences are allowed in byte literals: + +{{{with code "en" "escapes"}}} +-- in.txt -- + \xnn // arbitrary byte value defined as a 2-digit hexadecimal number + \nnn // arbitrary byte value defined as a 3-digit octal number +{{{end}}} + + +{{{with code "en" "bytes"}}} +-- in.cue -- +a: '\x03abc' +-- out.json -- +{ + "a": "A2FiYw==" +} +{{{end}}} diff --git a/content/docs/tour/types/bytes/gen_cache.cue b/content/docs/tour/types/bytes/gen_cache.cue new file mode 100644 index 000000000..f23cce652 --- /dev/null +++ b/content/docs/tour/types/bytes/gen_cache.cue @@ -0,0 +1,21 @@ +package site +{ + content: { + docs: { + tour: { + types: { + bytes: { + page: { + cache: { + code: { + escapes: "8vtA7ViI2sFYm8xmKowJXMB5ndr3JrCrE1tYBSagbyY=" + bytes: "/VCm4S2hcboOQNMR4h3VBDKFP2jW6AREcy5wdBCnWkc=" + } + } + } + } + } + } + } + } +} diff --git a/content/docs/tour/types/bytes/page.cue b/content/docs/tour/types/bytes/page.cue new file mode 100644 index 000000000..0450d8a11 --- /dev/null +++ b/content/docs/tour/types/bytes/page.cue @@ -0,0 +1,3 @@ +package site + +content: docs: tour: types: bytes: {} diff --git a/content/docs/tour/types/closed/en.md b/content/docs/tour/types/closed/en.md new file mode 100644 index 000000000..ffabbb7e0 --- /dev/null +++ b/content/docs/tour/types/closed/en.md @@ -0,0 +1,35 @@ +--- +title: "Closed structs" +weight: 7 +--- +Struct is the most important composite type in CUE. + +A struct may be open or closed. +A closed struct may only be merged with structs that have fields that +it defines to be allowed. +In other words, closing a struct is equivalent to requiring that all +other values be undefined. + +A closed struct can be created using the `close` builtin, +but are more commonly defined using a _definition_, defined next. + +{{{with code "en" "structs"}}} +exec cue eval -i structs.cue +cmp stdout '$ cue eval -i structs.cue' +-- structs.cue -- +a: close({ + field: int +}) + +b: a & { + feild: 3 +} +-- $ cue eval -i structs.cue -- +a: { + field: int +} +b: { + field: int + feild: _|_ // b.feild: field not allowed +} +{{{end}}} diff --git a/content/docs/tour/types/closed/gen_cache.cue b/content/docs/tour/types/closed/gen_cache.cue new file mode 100644 index 000000000..489de3ab8 --- /dev/null +++ b/content/docs/tour/types/closed/gen_cache.cue @@ -0,0 +1,20 @@ +package site +{ + content: { + docs: { + tour: { + types: { + closed: { + page: { + cache: { + code: { + structs: "5IUiLlZhc0s9SnEL9/LM8hFFJhAIWaR2G2SdH7i+yDI=" + } + } + } + } + } + } + } + } +} diff --git a/content/docs/tour/types/closed/page.cue b/content/docs/tour/types/closed/page.cue new file mode 100644 index 000000000..e1998b5cd --- /dev/null +++ b/content/docs/tour/types/closed/page.cue @@ -0,0 +1,3 @@ +package site + +content: docs: tour: types: closed: {} diff --git a/content/docs/tour/types/defaults/en.md b/content/docs/tour/types/defaults/en.md new file mode 100644 index 000000000..7f65a7ebf --- /dev/null +++ b/content/docs/tour/types/defaults/en.md @@ -0,0 +1,27 @@ +--- +title: "Default Values" +weight: 11 +--- +Elements of a disjunction may be marked as preferred. +If there is only one mark, or the users constraints a field enough such that +only one mark remains, that value is the default value. + +In the example, `replicas` defaults to `1`. +In the case of `protocol`, however, there are multiple definitions with +different, mutually incompatible defaults. +In that case, both `"tcp"` and `"udp"` are preferred and one must explicitly +specify either `"tcp"` or `"udp"` as if no marks were given. + +{{{with code "en" "defaults"}}} +#nofmt(in.cue) https://github.com/cue-lang/cue/issues/722 +-- in.cue -- +// any positive number, 1 is the default +replicas: uint | *1 + +// the default value is ambiguous +protocol: *"tcp" | "udp" +protocol: *"udp" | "tcp" +-- out.cue -- +replicas: 1 +protocol: "tcp" | "udp" +{{{end}}} diff --git a/content/docs/tour/types/defaults/gen_cache.cue b/content/docs/tour/types/defaults/gen_cache.cue new file mode 100644 index 000000000..b41a8ccd5 --- /dev/null +++ b/content/docs/tour/types/defaults/gen_cache.cue @@ -0,0 +1,20 @@ +package site +{ + content: { + docs: { + tour: { + types: { + defaults: { + page: { + cache: { + code: { + defaults: "GYWvuj2K32SEjbWwJoXXWPynXA6rQz9Y7aC/802wPYU=" + } + } + } + } + } + } + } + } +} diff --git a/content/docs/tour/types/defaults/page.cue b/content/docs/tour/types/defaults/page.cue new file mode 100644 index 000000000..424ea9691 --- /dev/null +++ b/content/docs/tour/types/defaults/page.cue @@ -0,0 +1,3 @@ +package site + +content: docs: tour: types: defaults: {} diff --git a/content/docs/tour/types/defs/en.md b/content/docs/tour/types/defs/en.md new file mode 100644 index 000000000..a96f3db48 --- /dev/null +++ b/content/docs/tour/types/defs/en.md @@ -0,0 +1,36 @@ +--- +title: "Definitions" +weight: 8 +--- +A definition, indicated by an identifier starting with `#` or `_#`, +defines values that +are not output when converting a configuration to a concrete value. +They are used to define schema against which concrete values can +be validated. + +Structs defined by definitions are implicitly closed. + +{{{with code "en" "definitions"}}} +exec cue eval -ic defs.cue +cmp stdout '$ cue eval -ic defs.cue' +-- defs.cue -- +msg: "Hello \(#Name)!" + +#Name: "world" + +#A: { + field: int +} + +a: #A & {field: 3} +err: #A & {feild: 3} +-- $ cue eval -ic defs.cue -- +msg: "Hello world!" +a: { + field: 3 +} +err: { + field: int + feild: _|_ // err.feild: field not allowed +} +{{{end}}} diff --git a/content/docs/tour/types/defs/gen_cache.cue b/content/docs/tour/types/defs/gen_cache.cue new file mode 100644 index 000000000..3da41b8e5 --- /dev/null +++ b/content/docs/tour/types/defs/gen_cache.cue @@ -0,0 +1,20 @@ +package site +{ + content: { + docs: { + tour: { + types: { + defs: { + page: { + cache: { + code: { + definitions: "HvBicFp6ea1IbgYL/AnUUHGd+QLcKmzGWACUyG2vAqw=" + } + } + } + } + } + } + } + } +} diff --git a/content/docs/tour/types/defs/page.cue b/content/docs/tour/types/defs/page.cue new file mode 100644 index 000000000..af473e301 --- /dev/null +++ b/content/docs/tour/types/defs/page.cue @@ -0,0 +1,3 @@ +package site + +content: docs: tour: types: defs: {} diff --git a/content/docs/tour/types/disjunctions/en.md b/content/docs/tour/types/disjunctions/en.md new file mode 100644 index 000000000..9a6121fff --- /dev/null +++ b/content/docs/tour/types/disjunctions/en.md @@ -0,0 +1,36 @@ +--- +title: "Disjunctions" +weight: 10 +--- +Disjunctions, or sum types, define a new type that is one of several things. + +In the example, our `Conn` definition of earlier is augmented to define +the possible values for `protocol`: `"tcp"` or `"udp"`. +It is an error for a concrete `Conn` +to define anything else than these two values. + +{{{with code "en" "disjunctions"}}} +-- in.cue -- +#Conn: { + address: string + port: int + protocol: "tcp" | "udp" +} + +lossy: #Conn & { + address: "1.2.3.4" + port: 8888 + protocol: "udp" +} +-- out.cue -- +#Conn: { + address: string + port: int + protocol: "tcp" | "udp" +} +lossy: { + address: "1.2.3.4" + port: 8888 + protocol: "udp" +} +{{{end}}} diff --git a/content/docs/tour/types/disjunctions/gen_cache.cue b/content/docs/tour/types/disjunctions/gen_cache.cue new file mode 100644 index 000000000..fa6eee326 --- /dev/null +++ b/content/docs/tour/types/disjunctions/gen_cache.cue @@ -0,0 +1,20 @@ +package site +{ + content: { + docs: { + tour: { + types: { + disjunctions: { + page: { + cache: { + code: { + disjunctions: "Oj2iLfJe3aY3Tpmi9KhBZ8Ox9h7PMCJUN6ZhcvSxFL0=" + } + } + } + } + } + } + } + } +} diff --git a/content/docs/tour/types/disjunctions/page.cue b/content/docs/tour/types/disjunctions/page.cue new file mode 100644 index 000000000..beff323ee --- /dev/null +++ b/content/docs/tour/types/disjunctions/page.cue @@ -0,0 +1,3 @@ +package site + +content: docs: tour: types: disjunctions: {} diff --git a/content/docs/tour/types/lists/en.md b/content/docs/tour/types/lists/en.md new file mode 100644 index 000000000..6fb445102 --- /dev/null +++ b/content/docs/tour/types/lists/en.md @@ -0,0 +1,44 @@ +--- +title: "Lists" +weight: 15 +--- +Lists define arbitrary sequences of CUE values. +A list can be closed or open ended. +Open-ended lists may have some predefined elements, but may have +additional, possibly typed elements. + +In the example we define `IP` to be a list of `4` elements of type `uint8`, which +is a predeclared value of `>=0 & <=255`. +`PrivateIP` defines the IP ranges defined for private use. +Note that as it is already defined to be an `IP`, the length of the list +is already fixed at `4` and we do not have to specify a value for all elements. +Also note that instead of writing `...uint8`, we could have written `...` +as the type constraint is already implied by `IP`. + +The output contains a valid private IP address (`myIP`) +and an invalid one (`yourIP`). + +{{{with code "en" "lists"}}} +exec cue eval -i lists.cue +cmp stdout '$ cue eval -i lists.cue' +-- lists.cue -- +import "list" + +IP: list.Repeat([ uint8], 4) + +PrivateIP: IP +PrivateIP: [10, ...uint8] | + [192, 168, ...] | + [172, >=16 & <=32, ...] + +myIP: PrivateIP +myIP: [10, 2, 3, 4] + +yourIP: PrivateIP +yourIP: [11, 1, 2, 3] +-- $ cue eval -i lists.cue -- +IP: [uint8, uint8, uint8, uint8] +PrivateIP: [10, uint8, uint8, uint8] | [192, 168, uint8, uint8] | [172, uint & >=16 & <=32, uint8, uint8] +myIP: [10, 2, 3, 4] +yourIP: _|_ // yourIP: 3 errors in empty disjunction: (and 3 more errors) +{{{end}}} diff --git a/content/docs/tour/types/lists/gen_cache.cue b/content/docs/tour/types/lists/gen_cache.cue new file mode 100644 index 000000000..7ecf6c2f8 --- /dev/null +++ b/content/docs/tour/types/lists/gen_cache.cue @@ -0,0 +1,20 @@ +package site +{ + content: { + docs: { + tour: { + types: { + lists: { + page: { + cache: { + code: { + lists: "pdG2OyTdDyfCmtaFmU/Qbk26uHYBngSgADHNd8Q+8qo=" + } + } + } + } + } + } + } + } +} diff --git a/content/docs/tour/types/lists/page.cue b/content/docs/tour/types/lists/page.cue new file mode 100644 index 000000000..6bb7c5007 --- /dev/null +++ b/content/docs/tour/types/lists/page.cue @@ -0,0 +1,3 @@ +package site + +content: docs: tour: types: lists: {} diff --git a/content/docs/tour/types/numbers/en.md b/content/docs/tour/types/numbers/en.md new file mode 100644 index 000000000..51ee6b344 --- /dev/null +++ b/content/docs/tour/types/numbers/en.md @@ -0,0 +1,44 @@ +--- +title: "Numbers" +weight: 3 +--- +CUE defines two kinds of numbers. +Integers, denoted `int`, are whole, or integral, numbers. +Floats, denoted `float`, are decimal floating point numbers. + +An integer literal (e.g. `4`) can be of either type, but defaults to `int`. +A floating point literal (e.g. `4.0`) is only compatible with `float`. + +In the example, the result of `b` is a `float` and cannot be +used as an `int` without conversion. + +CUE also adds a variety of sugar for writing numbers. + +{{{with code "en" "number"}}} +exec cue eval -i numbers.cue +cmp stdout '$ cue eval -i numbers.cue' +-- numbers.cue -- +a: int +a: 4 // type int + +b: number +b: 4.0 // type float + +c: int +c: 4.0 + +d: 4 // will evaluate to type int (default) + +e: [ + 1_234, // 1234 + 5M, // 5_000_000 + 1.5Gi, // 1_610_612_736 + 0x1000_0000, // 268_435_456 +] +-- $ cue eval -i numbers.cue -- +a: 4 +b: 4.0 +c: _|_ // c: conflicting values int and 4.0 (mismatched types int and float) +d: 4 +e: [1_234, 5M, 1.5Gi, 0x1000_0000] +{{{end}}} diff --git a/content/docs/tour/types/numbers/gen_cache.cue b/content/docs/tour/types/numbers/gen_cache.cue new file mode 100644 index 000000000..8578b2eab --- /dev/null +++ b/content/docs/tour/types/numbers/gen_cache.cue @@ -0,0 +1,20 @@ +package site +{ + content: { + docs: { + tour: { + types: { + numbers: { + page: { + cache: { + code: { + number: "2knZKTvYPnDO1mFix1LHpipX2IKgJLjq0QkuA04VOb4=" + } + } + } + } + } + } + } + } +} diff --git a/content/docs/tour/types/numbers/page.cue b/content/docs/tour/types/numbers/page.cue new file mode 100644 index 000000000..ea7c272b1 --- /dev/null +++ b/content/docs/tour/types/numbers/page.cue @@ -0,0 +1,3 @@ +package site + +content: docs: tour: types: numbers: {} diff --git a/content/docs/tour/types/optional/en.md b/content/docs/tour/types/optional/en.md new file mode 100644 index 000000000..3d641ae38 --- /dev/null +++ b/content/docs/tour/types/optional/en.md @@ -0,0 +1,34 @@ +--- +title: "Structs" +weight: 9 +--- +Struct is the most important composite type in CUE. +Its members are called fields. + +A struct field may be optional. +One can use an optional field to indicate what the type should be if it were +specified. +A regular (or required) field, on the other hand, must be made concrete +for a configuration to be converted to, say, JSON. + +It is okay for an optional field to be bottom (`_|_`). +This just means that field may not be specified. + +{{{with code "en" "structs"}}} +exec cue eval -c structs.cue +cmp stdout '$ cue eval -c structs.cue' +-- structs.cue -- +#a: { + foo?: int + bar?: string + baz?: string +} +b: #a & { + foo: 3 + baz?: 2 // baz?: _|_ +} +-- $ cue eval -c structs.cue -- +b: { + foo: 3 +} +{{{end}}} diff --git a/content/docs/tour/types/optional/gen_cache.cue b/content/docs/tour/types/optional/gen_cache.cue new file mode 100644 index 000000000..2bfdfbda5 --- /dev/null +++ b/content/docs/tour/types/optional/gen_cache.cue @@ -0,0 +1,20 @@ +package site +{ + content: { + docs: { + tour: { + types: { + optional: { + page: { + cache: { + code: { + structs: "BfhnEjKLPjJdDngtz4i9pbNhL12CUS9r7jxM6UOuuGc=" + } + } + } + } + } + } + } + } +} diff --git a/content/docs/tour/types/optional/page.cue b/content/docs/tour/types/optional/page.cue new file mode 100644 index 000000000..9fdc9b43e --- /dev/null +++ b/content/docs/tour/types/optional/page.cue @@ -0,0 +1,3 @@ +package site + +content: docs: tour: types: optional: {} diff --git a/content/docs/tour/types/page.cue b/content/docs/tour/types/page.cue new file mode 100644 index 000000000..44ef04e86 --- /dev/null +++ b/content/docs/tour/types/page.cue @@ -0,0 +1,3 @@ +package site + +content: docs: tour: types: {} diff --git a/content/docs/tour/types/stringlit/en.md b/content/docs/tour/types/stringlit/en.md new file mode 100644 index 000000000..51fb3c8dc --- /dev/null +++ b/content/docs/tour/types/stringlit/en.md @@ -0,0 +1,33 @@ +--- +title: "String Literals" +weight: 4 +--- +CUE strings allow a richer set of escape sequences than JSON. + +CUE also supports multi-line strings, enclosed by a pair of triple quotes `"""`. +The opening quote must be followed by a newline. +The closing quote must also be on a newline. +The whitespace directly preceding the closing quote must match the preceding +whitespace on all other lines and is removed from these lines. + +Strings may also contain [interpolations](../../expressions/interpolation). + + + +{{{with code "en" "stringlit"}}} +#nofmt(in.cue) https://github.com/cue-lang/cue/issues/722 +-- in.cue -- +// 21-bit unicode characters +a: "\U0001F60E" // 😎 + +// multiline strings +b: """ + Hello + World! + """ +-- out.json -- +{ + "a": "😎", + "b": "Hello\nWorld!" +} +{{{end}}} diff --git a/content/docs/tour/types/stringlit/gen_cache.cue b/content/docs/tour/types/stringlit/gen_cache.cue new file mode 100644 index 000000000..83c1a76a7 --- /dev/null +++ b/content/docs/tour/types/stringlit/gen_cache.cue @@ -0,0 +1,20 @@ +package site +{ + content: { + docs: { + tour: { + types: { + stringlit: { + page: { + cache: { + code: { + stringlit: "qIYnlrmW5oSliq3lZsE7szarDkS2O8S9HBiQCpk26bo=" + } + } + } + } + } + } + } + } +} diff --git a/content/docs/tour/types/stringlit/page.cue b/content/docs/tour/types/stringlit/page.cue new file mode 100644 index 000000000..fe172b3a5 --- /dev/null +++ b/content/docs/tour/types/stringlit/page.cue @@ -0,0 +1,3 @@ +package site + +content: docs: tour: types: stringlit: {} diff --git a/content/docs/tour/types/stringraw/en.md b/content/docs/tour/types/stringraw/en.md new file mode 100644 index 000000000..a280a5fb3 --- /dev/null +++ b/content/docs/tour/types/stringraw/en.md @@ -0,0 +1,35 @@ +--- +title: "\"Raw\" Strings" +weight: 5 +--- +CUE does not support raw strings in the strictest sense. +Instead it allows modifying the escape delimiter by requiring +an arbitrary number of hash `#` signs after the backslash by +enclosing a string literal in an equal number of hash signs on either end. + +This works for normal and interpolated strings. +Quotes do not have to be escaped in such strings. + +{{{with code "en" "raw"}}} +-- in.cue -- +msg1: #"The sequence "\U0001F604" renders as \#U0001F604."# + +msg2: ##""" + A regular expression can conveniently be written as: + + #"\d{3}"# + + This construct works for bytes, strings and their + multi-line variants. + """## +-- out.cue -- +msg1: "The sequence \"\\U0001F604\" renders as 😄." +msg2: """ + A regular expression can conveniently be written as: + + #"\\d{3}"# + + This construct works for bytes, strings and their + multi-line variants. + """ +{{{end}}} diff --git a/content/docs/tour/types/stringraw/gen_cache.cue b/content/docs/tour/types/stringraw/gen_cache.cue new file mode 100644 index 000000000..70a6c9c0b --- /dev/null +++ b/content/docs/tour/types/stringraw/gen_cache.cue @@ -0,0 +1,20 @@ +package site +{ + content: { + docs: { + tour: { + types: { + stringraw: { + page: { + cache: { + code: { + raw: "U0gchBeRzURZ5cCrRnDHOIAQuXyzDYOAfQ7aJCE1Cx8=" + } + } + } + } + } + } + } + } +} diff --git a/content/docs/tour/types/stringraw/page.cue b/content/docs/tour/types/stringraw/page.cue new file mode 100644 index 000000000..e864cf840 --- /dev/null +++ b/content/docs/tour/types/stringraw/page.cue @@ -0,0 +1,3 @@ +package site + +content: docs: tour: types: stringraw: {} diff --git a/content/docs/tour/types/sumstruct/en.md b/content/docs/tour/types/sumstruct/en.md new file mode 100644 index 000000000..6d87549f3 --- /dev/null +++ b/content/docs/tour/types/sumstruct/en.md @@ -0,0 +1,28 @@ +--- +title: "Disjunctions of Structs" +weight: 12 +--- +Disjunctions work for any type. + +In this example we see that a `floor` of some specific house +has an exit on level 0 and 1, but not on any other floor. + + +{{{with code "en" "example"}}} +#nofmt(in.cue) https://github.com/cue-lang/cue/issues/722 +-- in.cue -- +// floor defines the specs of a floor in some house. +floor: { + level: int // the level on which this floor resides + hasExit: bool // is there a door to exit the house? +} + +// constraints on the possible values of floor. +floor: { + level: 0 | 1 + hasExit: true +} | { + level: -1 | 2 | 3 + hasExit: false +} +{{{end}}} diff --git a/content/docs/tour/types/sumstruct/gen_cache.cue b/content/docs/tour/types/sumstruct/gen_cache.cue new file mode 100644 index 000000000..e20408f54 --- /dev/null +++ b/content/docs/tour/types/sumstruct/gen_cache.cue @@ -0,0 +1,20 @@ +package site +{ + content: { + docs: { + tour: { + types: { + sumstruct: { + page: { + cache: { + code: { + example: "Dta9a8iiMAlQqK4iCev5FdEUO2vhDkbsq6aJGpM3ZvM=" + } + } + } + } + } + } + } + } +} diff --git a/content/docs/tour/types/sumstruct/page.cue b/content/docs/tour/types/sumstruct/page.cue new file mode 100644 index 000000000..8a06f6a23 --- /dev/null +++ b/content/docs/tour/types/sumstruct/page.cue @@ -0,0 +1,3 @@ +package site + +content: docs: tour: types: sumstruct: {} diff --git a/content/docs/tour/types/templates/en.md b/content/docs/tour/types/templates/en.md new file mode 100644 index 000000000..399ebde2b --- /dev/null +++ b/content/docs/tour/types/templates/en.md @@ -0,0 +1,49 @@ +--- +title: "Templates" +weight: 16 +--- +One of CUE's most powerful features is the ability +to specify optional fields in bulk. +This allows one to specify constraints, +or templates, +to be unified with each field of a struct. + +An optional field set is an expression in square brackets +to specify to which fields to apply a constraint +(currently only `string`, or all fields is supported). +Using an alias in the square brackets binds the +label of the matched field to the given identifier, +which can then be used within the template. + + +{{{with code "en" "templates"}}} +#nofmt(in.cue) https://github.com/cue-lang/cue/issues/722 +-- in.cue -- +// The following struct is unified with all elements in job. +// The name of each element is bound to Name and visible in the struct. +job: [Name=_]: { + name: Name + replicas: uint | *1 + command: string +} + +job: list: command: "ls" + +job: nginx: { + command: "nginx" + replicas: 2 +} +-- out.cue -- +job: { + list: { + name: "list" + replicas: 1 + command: "ls" + } + nginx: { + name: "nginx" + command: "nginx" + replicas: 2 + } +} +{{{end}}} diff --git a/content/docs/tour/types/templates/gen_cache.cue b/content/docs/tour/types/templates/gen_cache.cue new file mode 100644 index 000000000..5dc0d522f --- /dev/null +++ b/content/docs/tour/types/templates/gen_cache.cue @@ -0,0 +1,20 @@ +package site +{ + content: { + docs: { + tour: { + types: { + templates: { + page: { + cache: { + code: { + templates: "k4RzZr75Fd5nMTu1wU2sRHkK7indjqBU7/Wf6AaBdzk=" + } + } + } + } + } + } + } + } +} diff --git a/content/docs/tour/types/templates/page.cue b/content/docs/tour/types/templates/page.cue new file mode 100644 index 000000000..c15061b99 --- /dev/null +++ b/content/docs/tour/types/templates/page.cue @@ -0,0 +1,3 @@ +package site + +content: docs: tour: types: templates: {} diff --git a/content/docs/tour/types/types/en.md b/content/docs/tour/types/types/en.md new file mode 100644 index 000000000..6db5c44ca --- /dev/null +++ b/content/docs/tour/types/types/en.md @@ -0,0 +1,69 @@ +--- +title: "Type Hierarchy" +weight: 1 +--- +CUE defines the following type hierarchy + +{{{with code "en" "hierarchy"}}} +-- in.txt -- + null bool string bytes number struct list + / \ + int float +{{{end}}} + +In addition, CUE defines the values +bottom, or error, (denoted `_|_`) +that is an instance of all types and +top, or any, (denoted `_`) of which all types are an instance. + +Note how we use the terms types and values interchangeably. +CUE does not distinguish between types and values. +The term "type" merely refers to the kind of a value, +which may or may not be a concrete instance. + +In the example, `point` defines an arbitrary point, while `xaxis` and `yaxis` +define the points on the respective lines. +We say that `point`, `xaxis`, and `yaxis` are incomplete, +as they do not specify a specific point. +Incomplete values cannot be represented as JSON, +as it can only represent concrete values. + +The only concrete point is `origin`. +The `origin` is defined to be both on the x-axis and y-axis, which means it +must be at `0, 0`. +Here we see constraints in action: +`origin` evalutes to `0, 0`, even though we did not specify its coordinates +explicitly. + +{{{with code "en" "point"}}} +-- in.cue -- +point: { + x: number + y: number +} + +xaxis: point +xaxis: y: 0 + +yaxis: point +yaxis: x: 0 + +origin: xaxis & yaxis +-- out.cue -- +point: { + x: number + y: number +} +xaxis: { + x: number + y: 0 +} +yaxis: { + x: 0 + y: number +} +origin: { + x: 0 + y: 0 +} +{{{end}}} diff --git a/content/docs/tour/types/types/gen_cache.cue b/content/docs/tour/types/types/gen_cache.cue new file mode 100644 index 000000000..b628dd937 --- /dev/null +++ b/content/docs/tour/types/types/gen_cache.cue @@ -0,0 +1,21 @@ +package site +{ + content: { + docs: { + tour: { + types: { + types: { + page: { + cache: { + code: { + hierarchy: "O0e9JEn9KKwEX2IL0CYB+3fuh3U6YCHQrs376Vgq+l8=" + point: "CP9iVPF3mFvBtbsKFTmuDus8GwAvTsUojOpgftiV3vA=" + } + } + } + } + } + } + } + } +} diff --git a/content/docs/tour/types/types/page.cue b/content/docs/tour/types/types/page.cue new file mode 100644 index 000000000..d507bb46a --- /dev/null +++ b/content/docs/tour/types/types/page.cue @@ -0,0 +1,3 @@ +package site + +content: docs: tour: types: types: {} diff --git a/hugo/content/en/docs/tour/types/_index.md b/hugo/content/en/docs/tour/types/_index.md new file mode 100644 index 000000000..b529b78b2 --- /dev/null +++ b/hugo/content/en/docs/tour/types/_index.md @@ -0,0 +1,9 @@ +--- +title: "Types and Values" +--- + +This tour demonstrates the hierarchy of primitive and complex types that CUE +makes available, along with common methods for constraining and combining these +types. + +## Contents diff --git a/hugo/content/en/docs/tour/types/bottom/index.md b/hugo/content/en/docs/tour/types/bottom/index.md new file mode 100644 index 000000000..71da54491 --- /dev/null +++ b/hugo/content/en/docs/tour/types/bottom/index.md @@ -0,0 +1,34 @@ +--- +title: "Bottom / Error" +weight: 2 +--- +Specifying duplicate fields with conflicting values results in an error +or bottom. +_Bottom_ is a special value in CUE, denoted `_|_`, that indicates an +error such as conflicting values. +Any error in CUE results in `_|_`. +Logically all errors are equal, although errors may be associated with +metadata such as an error message. + +Note that an error is different from `null`: `null` is a valid value, +whereas `_|_` is not. + +{{< code-tabs >}} +{{< code-tab name="bottom.cue" language="text" area="top-left" >}} +a: 4 +a: 5 + +l: [ 1, 2] +l: [ 1, 3] + +list: [0, 1, 2] +val: list[3] +{{< /code-tab >}} +{{< code-tab name="$ cue eval -i bottom.cue" language="text" area="top-right" >}} +a: _|_ // a: conflicting values 5 and 4 +l: [1, _|_, // l.1: conflicting values 3 and 2 +] +list: [0, 1, 2] +val: _|_ // val: index out of range [3] with length 3 +{{< /code-tab >}} +{{< /code-tabs >}} diff --git a/hugo/content/en/docs/tour/types/bounddef/index.md b/hugo/content/en/docs/tour/types/bounddef/index.md new file mode 100644 index 000000000..34fae75c3 --- /dev/null +++ b/hugo/content/en/docs/tour/types/bounddef/index.md @@ -0,0 +1,42 @@ +--- +title: "Predefined Bounds" +weight: 14 +--- +CUE numbers have arbitrary precision. +Also there is no unsigned integer type. + +CUE defines the following predefined identifiers to restrict the bounds of +integers to common values. + +```text +uint: >=0 +uint8: >=0 & <=255 +int8: >=-128 & <=127 +uint16: >=0 & <=65536 +int16: >=-32_768 & <=32_767 +rune: >=0 & <=0x10FFFF +uint32: >=0 & <=4_294_967_296 +int32: >=-2_147_483_648 & <=2_147_483_647 +uint64: >=0 & <=18_446_744_073_709_551_615 +int64: >=-9_223_372_036_854_775_808 & <=9_223_372_036_854_775_807 +int128: >=-170_141_183_460_469_231_731_687_303_715_884_105_728 & + <=170_141_183_460_469_231_731_687_303_715_884_105_727 +uint128: >=0 & <=340_282_366_920_938_463_463_374_607_431_768_211_455 +``` + +{{< code-tabs >}} +{{< code-tab name="bound.cue" language="text" area="top-left" >}} +#positive: uint +#byte: uint8 +#word: int32 + +a: #positive & -1 +b: #byte & 128 +c: #word & 2_000_000_000 +{{< /code-tab >}} +{{< code-tab name="$ cue eval -ic bound.cue" language="text" area="top-right" >}} +a: _|_ // a: invalid value -1 (out of bound >=0) +b: 128 +c: 2000000000 +{{< /code-tab >}} +{{< /code-tabs >}} diff --git a/hugo/content/en/docs/tour/types/bounds/index.md b/hugo/content/en/docs/tour/types/bounds/index.md new file mode 100644 index 000000000..aab55851a --- /dev/null +++ b/hugo/content/en/docs/tour/types/bounds/index.md @@ -0,0 +1,39 @@ +--- +title: "Bounds" +weight: 13 +--- +Bounds define a lower bound, upper bound, or inequality for a certain value. +They work on numbers, strings, bytes and null. + +The bound is defined for all values for which the corresponding comparison +operation is defined. +For instance `>5.0` allows all floating point values greater than `5.0`, +whereas `<0` allows all negative numbers (int or float). + + +{{< code-tabs >}} +{{< code-tab name="bounds.cue" language="text" area="top-left" >}} +#rn: >=3 & <8 // type int | float + +#ri: >=3 & <8 & int // type int + +#rf: >=3 & <=8.0 // type float +#rs: >="a" & <"mo" + +a: #rn & 3.5 +b: #ri & 3.5 +c: #rf & 3 +d: #rs & "ma" +e: #rs & "mu" + +r1: #rn & >=5 & <10 +{{< /code-tab >}} +{{< code-tab name="$ cue eval -ic bounds.cue" language="text" area="top-right" >}} +a: 3.5 +b: _|_ // b: conflicting values int and 3.5 (mismatched types int and float) +c: 3 +d: "ma" +e: _|_ // e: invalid value "mu" (out of bound <"mo") +r1: >=5 & <8 +{{< /code-tab >}} +{{< /code-tabs >}} diff --git a/hugo/content/en/docs/tour/types/bytes/index.md b/hugo/content/en/docs/tour/types/bytes/index.md new file mode 100644 index 000000000..b9e288e87 --- /dev/null +++ b/hugo/content/en/docs/tour/types/bytes/index.md @@ -0,0 +1,25 @@ +--- +title: "Bytes" +weight: 6 +--- +CUE distinguishes between a `string` and a `bytes` type. +Bytes are converted to base64 when emitting JSON. +Byte literals are defined with single quotes. +The following additional escape sequences are allowed in byte literals: + +```txt + \xnn // arbitrary byte value defined as a 2-digit hexadecimal number + \nnn // arbitrary byte value defined as a 3-digit octal number +``` + + +{{< code-tabs >}} +{{< code-tab name="CUE" language="text" area="top-left" >}} +a: '\x03abc' +{{< /code-tab >}} +{{< code-tab name="JSON" language="json" type="terminal" area="top-right" >}} +{ + "a": "A2FiYw==" +} +{{< /code-tab >}} +{{< /code-tabs >}} diff --git a/hugo/content/en/docs/tour/types/closed/index.md b/hugo/content/en/docs/tour/types/closed/index.md new file mode 100644 index 000000000..29d4ef369 --- /dev/null +++ b/hugo/content/en/docs/tour/types/closed/index.md @@ -0,0 +1,35 @@ +--- +title: "Closed structs" +weight: 7 +--- +Struct is the most important composite type in CUE. + +A struct may be open or closed. +A closed struct may only be merged with structs that have fields that +it defines to be allowed. +In other words, closing a struct is equivalent to requiring that all +other values be undefined. + +A closed struct can be created using the `close` builtin, +but are more commonly defined using a _definition_, defined next. + +{{< code-tabs >}} +{{< code-tab name="structs.cue" language="text" area="top-left" >}} +a: close({ + field: int +}) + +b: a & { + feild: 3 +} +{{< /code-tab >}} +{{< code-tab name="$ cue eval -i structs.cue" language="text" area="top-right" >}} +a: { + field: int +} +b: { + field: int + feild: _|_ // b.feild: field not allowed +} +{{< /code-tab >}} +{{< /code-tabs >}} diff --git a/hugo/content/en/docs/tour/types/defaults/index.md b/hugo/content/en/docs/tour/types/defaults/index.md new file mode 100644 index 000000000..8ed4ebff5 --- /dev/null +++ b/hugo/content/en/docs/tour/types/defaults/index.md @@ -0,0 +1,28 @@ +--- +title: "Default Values" +weight: 11 +--- +Elements of a disjunction may be marked as preferred. +If there is only one mark, or the users constraints a field enough such that +only one mark remains, that value is the default value. + +In the example, `replicas` defaults to `1`. +In the case of `protocol`, however, there are multiple definitions with +different, mutually incompatible defaults. +In that case, both `"tcp"` and `"udp"` are preferred and one must explicitly +specify either `"tcp"` or `"udp"` as if no marks were given. + +{{< code-tabs >}} +{{< code-tab name="CUE" language="text" area="top-left" >}} +// any positive number, 1 is the default +replicas: uint | *1 + +// the default value is ambiguous +protocol: *"tcp" | "udp" +protocol: *"udp" | "tcp" +{{< /code-tab >}} +{{< code-tab name="CUE" language="text" type="terminal" area="top-right" >}} +replicas: 1 +protocol: "tcp" | "udp" +{{< /code-tab >}} +{{< /code-tabs >}} diff --git a/hugo/content/en/docs/tour/types/defs/index.md b/hugo/content/en/docs/tour/types/defs/index.md new file mode 100644 index 000000000..ff78e12d1 --- /dev/null +++ b/hugo/content/en/docs/tour/types/defs/index.md @@ -0,0 +1,36 @@ +--- +title: "Definitions" +weight: 8 +--- +A definition, indicated by an identifier starting with `#` or `_#`, +defines values that +are not output when converting a configuration to a concrete value. +They are used to define schema against which concrete values can +be validated. + +Structs defined by definitions are implicitly closed. + +{{< code-tabs >}} +{{< code-tab name="defs.cue" language="text" area="top-left" >}} +msg: "Hello \(#Name)!" + +#Name: "world" + +#A: { + field: int +} + +a: #A & {field: 3} +err: #A & {feild: 3} +{{< /code-tab >}} +{{< code-tab name="$ cue eval -ic defs.cue" language="text" area="top-right" >}} +msg: "Hello world!" +a: { + field: 3 +} +err: { + field: int + feild: _|_ // err.feild: field not allowed +} +{{< /code-tab >}} +{{< /code-tabs >}} diff --git a/hugo/content/en/docs/tour/types/disjunctions/index.md b/hugo/content/en/docs/tour/types/disjunctions/index.md new file mode 100644 index 000000000..bd27aa7af --- /dev/null +++ b/hugo/content/en/docs/tour/types/disjunctions/index.md @@ -0,0 +1,38 @@ +--- +title: "Disjunctions" +weight: 10 +--- +Disjunctions, or sum types, define a new type that is one of several things. + +In the example, our `Conn` definition of earlier is augmented to define +the possible values for `protocol`: `"tcp"` or `"udp"`. +It is an error for a concrete `Conn` +to define anything else than these two values. + +{{< code-tabs >}} +{{< code-tab name="CUE" language="text" area="top-left" >}} +#Conn: { + address: string + port: int + protocol: "tcp" | "udp" +} + +lossy: #Conn & { + address: "1.2.3.4" + port: 8888 + protocol: "udp" +} +{{< /code-tab >}} +{{< code-tab name="CUE" language="text" type="terminal" area="top-right" >}} +#Conn: { + address: string + port: int + protocol: "tcp" | "udp" +} +lossy: { + address: "1.2.3.4" + port: 8888 + protocol: "udp" +} +{{< /code-tab >}} +{{< /code-tabs >}} diff --git a/hugo/content/en/docs/tour/types/lists/index.md b/hugo/content/en/docs/tour/types/lists/index.md new file mode 100644 index 000000000..7faa92030 --- /dev/null +++ b/hugo/content/en/docs/tour/types/lists/index.md @@ -0,0 +1,44 @@ +--- +title: "Lists" +weight: 15 +--- +Lists define arbitrary sequences of CUE values. +A list can be closed or open ended. +Open-ended lists may have some predefined elements, but may have +additional, possibly typed elements. + +In the example we define `IP` to be a list of `4` elements of type `uint8`, which +is a predeclared value of `>=0 & <=255`. +`PrivateIP` defines the IP ranges defined for private use. +Note that as it is already defined to be an `IP`, the length of the list +is already fixed at `4` and we do not have to specify a value for all elements. +Also note that instead of writing `...uint8`, we could have written `...` +as the type constraint is already implied by `IP`. + +The output contains a valid private IP address (`myIP`) +and an invalid one (`yourIP`). + +{{< code-tabs >}} +{{< code-tab name="lists.cue" language="text" area="top-left" >}} +import "list" + +IP: list.Repeat([ uint8], 4) + +PrivateIP: IP +PrivateIP: [10, ...uint8] | + [192, 168, ...] | + [172, >=16 & <=32, ...] + +myIP: PrivateIP +myIP: [10, 2, 3, 4] + +yourIP: PrivateIP +yourIP: [11, 1, 2, 3] +{{< /code-tab >}} +{{< code-tab name="$ cue eval -i lists.cue" language="text" area="top-right" >}} +IP: [uint8, uint8, uint8, uint8] +PrivateIP: [10, uint8, uint8, uint8] | [192, 168, uint8, uint8] | [172, uint & >=16 & <=32, uint8, uint8] +myIP: [10, 2, 3, 4] +yourIP: _|_ // yourIP: 3 errors in empty disjunction: (and 3 more errors) +{{< /code-tab >}} +{{< /code-tabs >}} diff --git a/hugo/content/en/docs/tour/types/numbers/index.md b/hugo/content/en/docs/tour/types/numbers/index.md new file mode 100644 index 000000000..36e09943c --- /dev/null +++ b/hugo/content/en/docs/tour/types/numbers/index.md @@ -0,0 +1,44 @@ +--- +title: "Numbers" +weight: 3 +--- +CUE defines two kinds of numbers. +Integers, denoted `int`, are whole, or integral, numbers. +Floats, denoted `float`, are decimal floating point numbers. + +An integer literal (e.g. `4`) can be of either type, but defaults to `int`. +A floating point literal (e.g. `4.0`) is only compatible with `float`. + +In the example, the result of `b` is a `float` and cannot be +used as an `int` without conversion. + +CUE also adds a variety of sugar for writing numbers. + +{{< code-tabs >}} +{{< code-tab name="numbers.cue" language="text" area="top-left" >}} +a: int +a: 4 // type int + +b: number +b: 4.0 // type float + +c: int +c: 4.0 + +d: 4 // will evaluate to type int (default) + +e: [ + 1_234, // 1234 + 5M, // 5_000_000 + 1.5Gi, // 1_610_612_736 + 0x1000_0000, // 268_435_456 +] +{{< /code-tab >}} +{{< code-tab name="$ cue eval -i numbers.cue" language="text" area="top-right" >}} +a: 4 +b: 4.0 +c: _|_ // c: conflicting values int and 4.0 (mismatched types int and float) +d: 4 +e: [1_234, 5M, 1.5Gi, 0x1000_0000] +{{< /code-tab >}} +{{< /code-tabs >}} diff --git a/hugo/content/en/docs/tour/types/optional/index.md b/hugo/content/en/docs/tour/types/optional/index.md new file mode 100644 index 000000000..fdf1d2159 --- /dev/null +++ b/hugo/content/en/docs/tour/types/optional/index.md @@ -0,0 +1,34 @@ +--- +title: "Structs" +weight: 9 +--- +Struct is the most important composite type in CUE. +Its members are called fields. + +A struct field may be optional. +One can use an optional field to indicate what the type should be if it were +specified. +A regular (or required) field, on the other hand, must be made concrete +for a configuration to be converted to, say, JSON. + +It is okay for an optional field to be bottom (`_|_`). +This just means that field may not be specified. + +{{< code-tabs >}} +{{< code-tab name="structs.cue" language="text" area="top-left" >}} +#a: { + foo?: int + bar?: string + baz?: string +} +b: #a & { + foo: 3 + baz?: 2 // baz?: _|_ +} +{{< /code-tab >}} +{{< code-tab name="$ cue eval -c structs.cue" language="text" area="top-right" >}} +b: { + foo: 3 +} +{{< /code-tab >}} +{{< /code-tabs >}} diff --git a/hugo/content/en/docs/tour/types/stringlit/index.md b/hugo/content/en/docs/tour/types/stringlit/index.md new file mode 100644 index 000000000..cb8c7e26f --- /dev/null +++ b/hugo/content/en/docs/tour/types/stringlit/index.md @@ -0,0 +1,34 @@ +--- +title: "String Literals" +weight: 4 +--- +CUE strings allow a richer set of escape sequences than JSON. + +CUE also supports multi-line strings, enclosed by a pair of triple quotes `"""`. +The opening quote must be followed by a newline. +The closing quote must also be on a newline. +The whitespace directly preceding the closing quote must match the preceding +whitespace on all other lines and is removed from these lines. + +Strings may also contain [interpolations](../../expressions/interpolation). + + + +{{< code-tabs >}} +{{< code-tab name="CUE" language="text" area="top-left" >}} +// 21-bit unicode characters +a: "\U0001F60E" // 😎 + +// multiline strings +b: """ + Hello + World! + """ +{{< /code-tab >}} +{{< code-tab name="JSON" language="json" type="terminal" area="top-right" >}} +{ + "a": "😎", + "b": "Hello\nWorld!" +} +{{< /code-tab >}} +{{< /code-tabs >}} diff --git a/hugo/content/en/docs/tour/types/stringraw/index.md b/hugo/content/en/docs/tour/types/stringraw/index.md new file mode 100644 index 000000000..d0a624b75 --- /dev/null +++ b/hugo/content/en/docs/tour/types/stringraw/index.md @@ -0,0 +1,37 @@ +--- +title: "\"Raw\" Strings" +weight: 5 +--- +CUE does not support raw strings in the strictest sense. +Instead it allows modifying the escape delimiter by requiring +an arbitrary number of hash `#` signs after the backslash by +enclosing a string literal in an equal number of hash signs on either end. + +This works for normal and interpolated strings. +Quotes do not have to be escaped in such strings. + +{{< code-tabs >}} +{{< code-tab name="CUE" language="text" area="top-left" >}} +msg1: #"The sequence "\U0001F604" renders as \#U0001F604."# + +msg2: ##""" + A regular expression can conveniently be written as: + + #"\d{3}"# + + This construct works for bytes, strings and their + multi-line variants. + """## +{{< /code-tab >}} +{{< code-tab name="CUE" language="text" type="terminal" area="top-right" >}} +msg1: "The sequence \"\\U0001F604\" renders as 😄." +msg2: """ + A regular expression can conveniently be written as: + + #"\\d{3}"# + + This construct works for bytes, strings and their + multi-line variants. + """ +{{< /code-tab >}} +{{< /code-tabs >}} diff --git a/hugo/content/en/docs/tour/types/sumstruct/index.md b/hugo/content/en/docs/tour/types/sumstruct/index.md new file mode 100644 index 000000000..578290946 --- /dev/null +++ b/hugo/content/en/docs/tour/types/sumstruct/index.md @@ -0,0 +1,26 @@ +--- +title: "Disjunctions of Structs" +weight: 12 +--- +Disjunctions work for any type. + +In this example we see that a `floor` of some specific house +has an exit on level 0 and 1, but not on any other floor. + + +```text +// floor defines the specs of a floor in some house. +floor: { + level: int // the level on which this floor resides + hasExit: bool // is there a door to exit the house? +} + +// constraints on the possible values of floor. +floor: { + level: 0 | 1 + hasExit: true +} | { + level: -1 | 2 | 3 + hasExit: false +} +``` diff --git a/hugo/content/en/docs/tour/types/templates/index.md b/hugo/content/en/docs/tour/types/templates/index.md new file mode 100644 index 000000000..8fdb9a516 --- /dev/null +++ b/hugo/content/en/docs/tour/types/templates/index.md @@ -0,0 +1,50 @@ +--- +title: "Templates" +weight: 16 +--- +One of CUE's most powerful features is the ability +to specify optional fields in bulk. +This allows one to specify constraints, +or templates, +to be unified with each field of a struct. + +An optional field set is an expression in square brackets +to specify to which fields to apply a constraint +(currently only `string`, or all fields is supported). +Using an alias in the square brackets binds the +label of the matched field to the given identifier, +which can then be used within the template. + + +{{< code-tabs >}} +{{< code-tab name="CUE" language="text" area="top-left" >}} +// The following struct is unified with all elements in job. +// The name of each element is bound to Name and visible in the struct. +job: [Name=_]: { + name: Name + replicas: uint | *1 + command: string +} + +job: list: command: "ls" + +job: nginx: { + command: "nginx" + replicas: 2 +} +{{< /code-tab >}} +{{< code-tab name="CUE" language="text" type="terminal" area="top-right" >}} +job: { + list: { + name: "list" + replicas: 1 + command: "ls" + } + nginx: { + name: "nginx" + command: "nginx" + replicas: 2 + } +} +{{< /code-tab >}} +{{< /code-tabs >}} diff --git a/hugo/content/en/docs/tour/types/types/index.md b/hugo/content/en/docs/tour/types/types/index.md new file mode 100644 index 000000000..6227fcee7 --- /dev/null +++ b/hugo/content/en/docs/tour/types/types/index.md @@ -0,0 +1,70 @@ +--- +title: "Type Hierarchy" +weight: 1 +--- +CUE defines the following type hierarchy + +```txt + null bool string bytes number struct list + / \ + int float +``` + +In addition, CUE defines the values +bottom, or error, (denoted `_|_`) +that is an instance of all types and +top, or any, (denoted `_`) of which all types are an instance. + +Note how we use the terms types and values interchangeably. +CUE does not distinguish between types and values. +The term "type" merely refers to the kind of a value, +which may or may not be a concrete instance. + +In the example, `point` defines an arbitrary point, while `xaxis` and `yaxis` +define the points on the respective lines. +We say that `point`, `xaxis`, and `yaxis` are incomplete, +as they do not specify a specific point. +Incomplete values cannot be represented as JSON, +as it can only represent concrete values. + +The only concrete point is `origin`. +The `origin` is defined to be both on the x-axis and y-axis, which means it +must be at `0, 0`. +Here we see constraints in action: +`origin` evalutes to `0, 0`, even though we did not specify its coordinates +explicitly. + +{{< code-tabs >}} +{{< code-tab name="CUE" language="text" area="top-left" >}} +point: { + x: number + y: number +} + +xaxis: point +xaxis: y: 0 + +yaxis: point +yaxis: x: 0 + +origin: xaxis & yaxis +{{< /code-tab >}} +{{< code-tab name="CUE" language="text" type="terminal" area="top-right" >}} +point: { + x: number + y: number +} +xaxis: { + x: number + y: 0 +} +yaxis: { + x: 0 + y: number +} +origin: { + x: 0 + y: 0 +} +{{< /code-tab >}} +{{< /code-tabs >}}