ambiguous, or when data should be normalized prior to comparison, or
when a specific data type is required.
+=== Casting Behavior
+
+In general, casting data types of different sizes will fail. For
+example, casting an `octet` string of length `3` to `uint32` is
+impossible, because `uint32` data types are 4 bytes in length.
+
+However, in many cases casting from one data type will "just work".
+
+When the cast fails, the result is a `NULL` or empty value.
+
+==== IP Addresses
+
+Casting `ipv4addr` to `ipv6addr` will return an IPv6 address which
+contains the IPv4 address, with the upper bits as `::ffff`. This
+result is then a valid "IPv4-mapped IPv6 address".
+
+Casting `ipv6addr` to `ipv4addr` will work if the IPv6 address is a
+valid "IPv4-mapped IPv6 address".
+
+Similar rules apply to casting between IPv4 and IPv6 prefixes.
+
+Casting an IPv4 address to an IPv4 prefix is allowed, and will return
+a prefix of using a `/32`. Casting the other way is also allowed, but
+only if the prefix is `/32`.
+
+==== Numbers
+
+Numbers can generally be cast from one data type to another, if the
+input value can be represented in the new data type.
+
+For example, casting `uint8` to `uint16` will always succeed.
+However, casting a signed `int8` to `uint16` may fail, as negative
+values cannot be represented in the `uint16` data type.
+
+==== Octets
+
+Casting any data type to `octets` means returning the "raw" value of
+the underlying data type. For example, casting an IPv4 address of
+value `127.0.0.1` to `octets` will return the `octets` string
+`0x7f000001`.
+
+Casting an `octets` value to any other data type means interpreting
+the raw value as that data type, generally as if the data had been
+received from the network. For example, casting the `octets` string
+`0x7f000001` to `ipvaddr` will return the IPv4 address `127.0.0.1`.
+
+==== Strings
+
+Casting any data type to `string` means _printing_ the data type to a
+string, and assigning the resulting value to the `string`. For
+`octets`, this means that the output is a hex string, prefixed with
+`0x`.
+
+Casting a `string` value to another data type means _parsing_ the
+string as that data type.
+
=== Expressions
Unlang xref:unlang/expression.adoc[expressions] can use casts, too, as
+++ /dev/null
-= Double-Quoted Strings
-
-.Syntax
-`"string"`
-
-A double-quoted string is interpreted via the usual rules in
-programming languages for double quoted strings. The double-quote
-character can be placed in a string by escaping it with a backslash.
-Carriage returns and line-feeds can also be used via the usual `\r` and
-`\n` syntax.
-
-The main difference between the single and double quoted strings is
-that the double quoted strings can be dynamically expanded. The syntax
-`${...}` is used for parse-time expansion and `%{...}` is used for
-run-time expansion. The difference between the two methods is that the
-`${...}` form is expanded when the server loads the configuration
-files and is valid anywhere in the configuration files. The `%{...}`
-link:xlat.adoc[string expansion] form is valid only in conditional
-expressions and attribute assignments.
-
-The output of the dynamic expansion can be interpreted as a string,
-a number, or an IP address, depending on its context.
-
-Note that the interpretation of text _strongly_ depends on the
-context. The text `0000` can be interpreted as a data type
-"integer", having value zero, or a data type "string", having value
-`"0000"`. In general when a particular piece of text is used, it is
-used with the context of a known attribute. That attribute has a
-link:data.adoc[data type], and the text will be interpreted as that
-data type.
-
-.Examples
-
-`"word"` +
-`"a string"` +
-`"this has embedded\ncharacters"`
-
-== Methods of Creating Strings
-
-There are a few different ways in which double-quoted strings can be
-created. The simplest is just an in-line string, as in `"string"`.
-However, strings can also be created via
-xref:unlang/expression.adoc[expressions]. and
-xref:xlat/index.adoc[dynamic expansions].
-
-In general, creating strings via xref:xlat/index.adoc[dynamic
-expansions] will result in the _printed_ version of the expansion
-being used.
-
-.Example of double-quoted string expansion
-[source,unlang]
-----
-"User-Name is %{User-Name}"
-"IP Address is %{reply.Framed-IP-Address}
-----
-
-Both of the above expansions will return the _printed_ version of the
-expansion. For `User-Name`, it will be the string version of the
-users name, as would be expected. However, for the
-`Framed-IP-Address` example, the printed version will be an ASCII
-string such as `192.0.2.1`, even though the actual IP address is a
-32-bit number.
-
-When a string is created via an
-xref:unlang/expression.adoc[expression] using the `+` operator, the
-resulting string can be quite different, depending on the inputs.
-
-.Example of casting to 'string'
-[source,unlang]
-----
-"User-Name is " + &User-Name
-"IP Address is " + (string) &reply.Framed-IP-Address
-----
-
-The output strings here (with casting) are the same as for the
-previous example. Note that we do not have to cast `&User-Name`,
-because it is already a string.
-
-.Example of casting to 'octets'
-[source,unlang]
-----
-"User-Name is " + (octets) &User-Name
-"IP Address is " + (octets) &reply.Framed-IP-Address
-----
-
-The output strings here are completely different than for the previous
-examples. The output data type is `octets`, and not `string`.
-
-
-// Copyright (C) 2021 Network RADIUS SAS. Licenced under CC-by-NC 4.0.
-// Development of this documentation was sponsored by Network RADIUS SAS.
.Syntax
`"string"`
-A double-quoted string allows escape sequences and xref:xlat/index.adoc[dynamic
-expansions]. As with xref:type/string/single.adoc[single-quoted strings], text
-within double quotes can include spaces.
+A double-quoted string allows escape sequences and
+xref:xlat/index.adoc[dynamic expansions]. As with
+xref:type/string/single.adoc[single-quoted strings], text within
+double quotes can include spaces.
The main difference between the single and double quoted strings is
that the double quoted strings can be dynamically expanded. The syntax
| `\x<oct><oct><oct>` | A byte whose numerical value is given by `<oct><oct><oct>` interpreted as an octal number.
|=====
+== Methods of Creating Strings
+
+There are a few different ways in which double-quoted strings can be
+created. The simplest is just an in-line string, as in `"string"`.
+However, strings can also be created via
+xref:unlang/expression.adoc[expressions]. and
+xref:xlat/index.adoc[dynamic expansions].
+
+In general, creating strings via xref:xlat/index.adoc[dynamic
+expansions] will result in the _printed_ version of the expansion
+being used.
+
+.Example of double-quoted string expansion
+[source,unlang]
+----
+"User-Name is %{User-Name}"
+"IP Address is %{reply.Framed-IP-Address}
+----
+
+Both of the above expansions will return the _printed_ version of the
+expansion. For `User-Name`, it will be the string version of the
+users name, as would be expected. However, for the
+`Framed-IP-Address` example, the printed version will be an ASCII
+string such as `192.0.2.1`, even though the actual IP address is a
+32-bit number.
+
+When a string is created via an
+xref:unlang/expression.adoc[expression] using the `+` operator, the
+resulting string can be quite different, depending on the inputs.
+
+.Example of casting to 'string'
+[source,unlang]
+----
+"User-Name is " + &User-Name
+"IP Address is " + (string) &reply.Framed-IP-Address
+----
+
+The output strings here (with casting) are the same as for the
+previous example. Note that we do not have to cast `&User-Name`,
+because it is already a string.
+
+.Example of casting to 'octets'
+[source,unlang]
+----
+"User-Name is " + (octets) &User-Name
+"IP Address is " + (octets) &reply.Framed-IP-Address
+----
+
+The output strings here are completely different than for the previous
+examples. The output data type is `octets`, and not `string`.
+
.Examples
`"word"` +