Implementing

Name encoding

View this section in the spec ↗

Covers the 20 name bits (UUID hex digits 1–5), written as the 1–4 characters before the . in a TNID string: 4 characters × 5 bits.

Alphabet

32 values: null (00000, padding only), 0–4, a–z. Value order is ASCII order, so names sort the same as strings and as bits: "a" < "b" < "z" both ways. Full table under Mapping.

Padding

Names shorter than 4 characters MUST be null-padded at the end (least significant bits). At least one character MUST be non-null.

"ab" encoded (20 bits):

✓ Valid:   [00110][00111][00000][00000]
              a      b    null   null

✗ Invalid: [00110][00000][00111][00000]
              a    null     b    null
           (non-null after null is invalid)

Validity

Reading name bits from a 128-bit value, reject:

  • all four characters null (empty name);
  • a non-null character after a null.

Every other combination is valid: all 32 values are a character or null.

Worked examples

Encoding "ab":

  1. Look up: a = 00110, b = 00111.
  2. Concatenate: 00110 00111.
  3. Null-pad to 20 bits: 00110 00111 00000 00000.
  4. Regroup into nibbles: 0011 0001 1100 0000 0000 = 0x31C00.

The 20-bit value is also the first five hex digits of the UUID:

NameBitsHex
a00110 00000 00000 0000030000
000001 00000 00000 0000008000
ab00110 00111 00000 0000031c00
a1b200110 00010 00111 00011308e3
post10101 10100 11000 11001ad319
test11001 01010 11000 11001cab19
user11010 11000 01010 10111d6157
zzzz11111 11111 11111 11111fffff

Mapping

Value = position in 01234abcdefghijklmnopqrstuvwxyz, counting from 1; null is 0. Read each column top to bottom.

00000 null   01000 c   10000 k   11000 s
00001 0      01001 d   10001 l   11001 t
00010 1      01010 e   10010 m   11010 u
00011 2      01011 f   10011 n   11011 v
00100 3      01100 g   10100 o   11100 w
00101 4      01101 h   10101 p   11101 x
00110 a      01110 i   10110 q   11110 y
00111 b      01111 j   10111 r   11111 z