Odin by Example: Runes

A rune represents a single Unicode code point. It is a signed 32-bit integer and a distinct type from i32.

Character literals use single quotes and produce untyped rune constants. They can be assigned to a rune variable or to an integer type that can hold the value.

Strings store UTF-8 encoded bytes. When you iterate a string with for-in, Odin decodes UTF-8 into runes. Indexing a string still gives bytes (u8), as shown in the Strings example.

The core:unicode/utf8 package provides procedures for converting between strings and rune slices.

$ odin run runes.odin -file
A
65
é
233

19990
A is uppercase
3
café
0 99
1 97
2 102
3 233
café
package main

import "core:fmt"
import "core:unicode/utf8"

main :: proc() {
	// A rune literal.
	r := 'A'
	fmt.println(r)

	// Untyped rune constants convert to integers.
	fmt.println(int(r))

	// Multi-byte Unicode characters work too.
	acc := 'é'
	fmt.println(acc)
	fmt.println(int(acc))

	// Characters outside the ASCII range.
	kanji := '世'
	fmt.println(kanji)
	fmt.println(int(kanji))

	// Runes are comparable and ordered.
	if 'A' <= r && r <= 'Z' {
		fmt.println("A is uppercase")
	}

	// Iterate a string to get runes. The index is the
	// byte offset, not the rune index.
	word := "café"
	fmt.println(len(word)) // byte length

	for r, i in word {
		fmt.println(i, r)
	}

	// Convert a string to a []rune slice.
	runes := utf8.string_to_runes(word)
	defer delete(runes)

	// Convert back to a string.
	back := utf8.runes_to_string(runes)
	defer delete(back)
	fmt.println(back)

	// Decode a single rune from a string at a byte
	// offset. The second return value is the number of
	// bytes consumed.
	r2, size := utf8.decode_rune_in_string(word)
	fmt.println(r2, size) // 'c', 1
}

← strings | structs →