<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Erdene-Ochir Sh</title>
    <description>The latest articles on DEV Community by Erdene-Ochir Sh (@erdeneochir_sh_e862b1f51).</description>
    <link>https://dev.to/erdeneochir_sh_e862b1f51</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4069871%2F585ef2c7-1ba2-485b-8fda-13c004c3f332.png</url>
      <title>DEV Community: Erdene-Ochir Sh</title>
      <link>https://dev.to/erdeneochir_sh_e862b1f51</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/erdeneochir_sh_e862b1f51"/>
    <language>en</language>
    <item>
      <title>UCE-8: fitting the world's living scripts into two bytes</title>
      <dc:creator>Erdene-Ochir Sh</dc:creator>
      <pubDate>Sun, 09 Aug 2026 14:09:36 +0000</pubDate>
      <link>https://dev.to/erdeneochir_sh_e862b1f51/uce-8-fitting-the-worlds-living-scripts-into-two-bytes-102j</link>
      <guid>https://dev.to/erdeneochir_sh_e862b1f51/uce-8-fitting-the-worlds-living-scripts-into-two-bytes-102j</guid>
      <description>&lt;p&gt;&lt;strong&gt;UCE-8&lt;/strong&gt; — &lt;em&gt;Unicode 3-byte variable-width Compact Encoding&lt;/em&gt; — is a character&lt;br&gt;
encoding sized for the world's living scripts, reaching 128 × 128 × 68 =&lt;br&gt;
1,114,112 characters in at most three bytes.&lt;/p&gt;

&lt;p&gt;UTF-8 charges most of the world's living languages three bytes per character.&lt;br&gt;
UCE-8 charges two. This is how it does that, what it measurably saves, and&lt;br&gt;
what it costs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Every figure in this article was produced by running&lt;br&gt;
&lt;a href="https://gitlab.com/eric.shagdarjav/uce/-/blob/main/docs/verify.py" rel="noopener noreferrer"&gt;verify.py&lt;/a&gt; against the reference implementation,&lt;br&gt;
&lt;a href="https://gitlab.com/eric.shagdarjav/uce/-/blob/main/uce_hibrid.py" rel="noopener noreferrer"&gt;uce_hibrid.py&lt;/a&gt;. Reviewer notes on the first draft are&lt;br&gt;
kept in &lt;a href="https://gitlab.com/eric.shagdarjav/uce/-/blob/main/docs/uce8-article-review.md" rel="noopener noreferrer"&gt;reviewer notes&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;In the text we use every day, characters are stored with a length of 1–4 bytes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UTF-8:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;English-language text = 1 byte&lt;/li&gt;
&lt;li&gt;European languages + Middle East = 2 bytes&lt;/li&gt;
&lt;li&gt;Asian and African languages = 3 bytes&lt;/li&gt;
&lt;li&gt;Languages that have fallen out of use = 4 bytes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;UCE-8&lt;/strong&gt;, instead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;English-language text = 1 byte&lt;/li&gt;
&lt;li&gt;Every language alive and in use today = 2 bytes&lt;/li&gt;
&lt;li&gt;Languages that have fallen out of use = 3 bytes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Which tier a script lands in was decided by Unicode's code-point ordering, not&lt;br&gt;
by how many people write in it. That is why Devanagari, Thai, Ethiopic and&lt;br&gt;
Chinese — between them the everyday scripts of billions — sit in UTF-8's&lt;br&gt;
expensive three-byte tier.&lt;/p&gt;
&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;1 byte = 8 bits = 256 possible values. Call the first 128 the &lt;strong&gt;low byte&lt;/strong&gt; and&lt;br&gt;
the last 128 the &lt;strong&gt;high byte&lt;/strong&gt;. The high bit is the length signal: a &lt;code&gt;high&lt;/code&gt;&lt;br&gt;
byte means "another byte follows," a &lt;code&gt;low&lt;/code&gt; byte means "the character ends&lt;br&gt;
here." Decoding stops the instant a low byte appears — no length field, no&lt;br&gt;
lookahead.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;byte pattern&lt;/th&gt;
&lt;th&gt;length&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;low&lt;/td&gt;
&lt;td&gt;1 byte&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;high, low&lt;/td&gt;
&lt;td&gt;2 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;high, high, low&lt;/td&gt;
&lt;td&gt;3 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That gives a self-terminating, three-tier scheme:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;tier&lt;/th&gt;
&lt;th&gt;byte pattern&lt;/th&gt;
&lt;th&gt;capacity&lt;/th&gt;
&lt;th&gt;covers&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0xxxxxxx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;plain ASCII&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;1xxxxxxx&lt;/code&gt; &lt;code&gt;0xxxxxxx&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;8,704&lt;/td&gt;
&lt;td&gt;68 pages, 128 characters each&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;1xxxxxxx&lt;/code&gt; &lt;code&gt;1xxxxxxx&lt;/code&gt; &lt;code&gt;0xxxxxxx&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;1,114,112&lt;/td&gt;
&lt;td&gt;every remaining code point&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The two positions have names, and they are just the high/low split above seen&lt;br&gt;
from the other side:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;lead byte&lt;/strong&gt; is a &lt;em&gt;high&lt;/em&gt; byte (&lt;code&gt;0x80&lt;/code&gt;–&lt;code&gt;0xFF&lt;/code&gt;). It always means "another
follows," and it carries the character's &lt;strong&gt;slot&lt;/strong&gt; — which of a page's 128
entries this is.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;trail byte&lt;/strong&gt; is a &lt;em&gt;low&lt;/em&gt; byte (&lt;code&gt;0x00&lt;/code&gt;–&lt;code&gt;0x7F&lt;/code&gt;). It &lt;strong&gt;terminates&lt;/strong&gt; the
character, and it is the &lt;strong&gt;page index&lt;/strong&gt;. Of its 128 possible values, 68 are
usable (see below), so tier 2 reaches 128 × 68 = &lt;strong&gt;8,704 characters in 2
bytes&lt;/strong&gt; where UTF-8 needs 3.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note the order, because it inverts the usual arrangement: the &lt;strong&gt;second&lt;/strong&gt; byte&lt;br&gt;
says which script you are in, and the &lt;strong&gt;first&lt;/strong&gt; says which letter of it. UTF-8&lt;br&gt;
puts the identifying information in the leading byte; UCE-8 puts it in the&lt;br&gt;
terminator. Devanagari न (U+0928) encodes as &lt;code&gt;A8 35&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A8  =  0x80 | 40   lead byte  — slot 40 of the page
35  =  page index  trail byte — the page holding U+0900–U+097F
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hold the lead byte at &lt;code&gt;A8&lt;/code&gt; and change only the trail byte, and the same slot&lt;br&gt;
number lands in a different script each time:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;bytes&lt;/th&gt;
&lt;th&gt;code point&lt;/th&gt;
&lt;th&gt;character&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;A8 35&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;U+0928&lt;/td&gt;
&lt;td&gt;न Devanagari NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;A8 45&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;U+0E28&lt;/td&gt;
&lt;td&gt;ศ Thai SO SALA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;A8 33&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;U+0628&lt;/td&gt;
&lt;td&gt;ب Arabic BEH&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That is the whole addressing scheme: the trail byte chooses the page, the lead&lt;br&gt;
byte chooses the entry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The tiers fit Unicode exactly.&lt;/strong&gt; Tier 3's capacity is 128 × 128 × 68 =&lt;br&gt;
1,114,112. Unicode's total code space is 17 × 65,536 = 1,114,112. The same&lt;br&gt;
number. UCE-8 covers all of Unicode with no waste and nothing spare — and&lt;br&gt;
encoding then decoding all 1,114,112 code points round-trips with zero&lt;br&gt;
failures.&lt;/p&gt;
&lt;h2&gt;
  
  
  Budgeting the 68 pages
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;page type&lt;/th&gt;
&lt;th&gt;pages&lt;/th&gt;
&lt;th&gt;slots&lt;/th&gt;
&lt;th&gt;what's in them&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Alphabetic world scripts&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;3,840&lt;/td&gt;
&lt;td&gt;Latin, Greek, Cyrillic, Armenian, Hebrew, Arabic, the Indic scripts, Thai, Lao, Tibetan, Myanmar, Georgian, Ethiopic, Khmer, Vietnamese, Kana + CJK punctuation, Mongolian, currencies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chinese&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;4,096&lt;/td&gt;
&lt;td&gt;the highest-frequency Han characters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Korean&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;768&lt;/td&gt;
&lt;td&gt;the highest-frequency Hangul syllables&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;68&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;8,704&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each category splits into two kinds of page:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;36 block pages&lt;/strong&gt; (28 world scripts + 8 Chinese) — a plain
128-code-point-aligned slice of Unicode, so the slot is arithmetic
(&lt;code&gt;code_point &amp;amp; 0x7F&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;32 indexed pages&lt;/strong&gt; (2 world + 24 Chinese + 6 Korean) — 128 entries of a
curated list, so the slot is a lookup.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Chinese and Korean are indexed rather than block-mapped because Unicode orders&lt;br&gt;
Han characters by radical and Hangul syllables by jamo combination, and&lt;br&gt;
neither follows frequency. The first 1,920 Hangul syllables that 15 block&lt;br&gt;
pages would cover reach only 28% of real Korean text; 6 indexed pages reach&lt;br&gt;
89%. All 3,500 characters of China's national standard primary set&lt;br&gt;
(通用规范汉字表) fit in 2 bytes, with 24 slots spare.&lt;/p&gt;

&lt;p&gt;The flip side of frequency-ordering is a fallback: 768 of 11,172 Hangul&lt;br&gt;
syllables and 4,096 of 20,992 CJK ideographs reach 2 bytes. The rest — rare&lt;br&gt;
syllables, proper names, loanwords, most Traditional Chinese — cost 3.&lt;/p&gt;
&lt;h2&gt;
  
  
  What the trail byte can and can't be
&lt;/h2&gt;

&lt;p&gt;Of the 128 possible trail values, 60 are excluded: the 33 control codes&lt;br&gt;
(&lt;code&gt;0x00&lt;/code&gt;–&lt;code&gt;0x1F&lt;/code&gt; plus &lt;code&gt;DEL&lt;/code&gt;) and space, plus 26 punctuation marks that carry&lt;br&gt;
structural meaning wherever text flows —&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;" &amp;amp; ' / &amp;lt; = &amp;gt; \ `     HTML, shell quoting, JSON strings, path separators
% , - . : ?           URL encoding, CSV, file extensions, key:value
# $ * + ; @ [ ] { | } shell, glob, email, JSON arrays and objects
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only 6 punctuation marks survive as trail bytes — &lt;code&gt;! ( ) ^ _ ~&lt;/code&gt; — and none is&lt;br&gt;
a metacharacter in JSON, CSV, URLs, file paths, or the shell.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two different claims live here, and only one of them is true.&lt;/strong&gt; A UCE-8&lt;br&gt;
stream will not &lt;em&gt;corrupt a parse&lt;/em&gt;: no excluded metacharacter can ever appear&lt;br&gt;
in encoded output. But the 68 trail bytes that &lt;em&gt;are&lt;/em&gt; used are mostly ASCII&lt;br&gt;
digits and letters, so a UCE-8 stream is &lt;strong&gt;not safe for naive matching&lt;/strong&gt;.&lt;br&gt;
Devanagari's page index is &lt;code&gt;0x35&lt;/code&gt; — the digit &lt;code&gt;5&lt;/code&gt; — so &lt;code&gt;नमस्ते&lt;/code&gt; encodes to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A8 35 AE 35 B8 35 CD 35 A4 35 C7 35
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Search that word plus the text &lt;code&gt;price: 5 dollars&lt;/code&gt; for the byte &lt;code&gt;"5"&lt;/code&gt; and you&lt;br&gt;
get 7 matches, one of which is a real digit. Every &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;LIKE '%…%'&lt;/code&gt;, and&lt;br&gt;
substring index over raw UCE-8 bytes inherits this.&lt;/p&gt;
&lt;h2&gt;
  
  
  What it actually saves
&lt;/h2&gt;

&lt;p&gt;The raw saving is deterministic: a character that cost 3 bytes costs 2, a flat&lt;br&gt;
33% for that tier. Real text is a mix, so real documents land lower. And&lt;br&gt;
because text is usually compressed in transit and at rest, the compressed&lt;br&gt;
figure is the one that decides most real deployments:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Sample&lt;/th&gt;
&lt;th&gt;UTF-8&lt;/th&gt;
&lt;th&gt;UCE-8&lt;/th&gt;
&lt;th&gt;raw&lt;/th&gt;
&lt;th&gt;gzip&lt;/th&gt;
&lt;th&gt;brotli&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Chinese (simplified)&lt;/td&gt;
&lt;td&gt;78&lt;/td&gt;
&lt;td&gt;52&lt;/td&gt;
&lt;td&gt;33.3%&lt;/td&gt;
&lt;td&gt;27.7%&lt;/td&gt;
&lt;td&gt;23.3%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Korean&lt;/td&gt;
&lt;td&gt;95&lt;/td&gt;
&lt;td&gt;69&lt;/td&gt;
&lt;td&gt;27.4%&lt;/td&gt;
&lt;td&gt;28.0%&lt;/td&gt;
&lt;td&gt;18.9%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Japanese&lt;/td&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;td&gt;70&lt;/td&gt;
&lt;td&gt;30.7%&lt;/td&gt;
&lt;td&gt;18.4%&lt;/td&gt;
&lt;td&gt;12.9%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Thai&lt;/td&gt;
&lt;td&gt;160&lt;/td&gt;
&lt;td&gt;107&lt;/td&gt;
&lt;td&gt;33.1%&lt;/td&gt;
&lt;td&gt;11.2%&lt;/td&gt;
&lt;td&gt;23.3%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Amharic&lt;/td&gt;
&lt;td&gt;92&lt;/td&gt;
&lt;td&gt;63&lt;/td&gt;
&lt;td&gt;31.5%&lt;/td&gt;
&lt;td&gt;13.7%&lt;/td&gt;
&lt;td&gt;11.3%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hindi&lt;/td&gt;
&lt;td&gt;169&lt;/td&gt;
&lt;td&gt;117&lt;/td&gt;
&lt;td&gt;30.8%&lt;/td&gt;
&lt;td&gt;9.3%&lt;/td&gt;
&lt;td&gt;11.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chinese (traditional)&lt;/td&gt;
&lt;td&gt;81&lt;/td&gt;
&lt;td&gt;59&lt;/td&gt;
&lt;td&gt;27.2%&lt;/td&gt;
&lt;td&gt;21.2%&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JSON with Chinese values&lt;/td&gt;
&lt;td&gt;55&lt;/td&gt;
&lt;td&gt;47&lt;/td&gt;
&lt;td&gt;14.5%&lt;/td&gt;
&lt;td&gt;12.5%&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Read this honestly and three things follow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The raw saving is real and reliable.&lt;/strong&gt; 27–33% across every script the&lt;br&gt;
2-byte tier was built for. If you are storing text uncompressed — in memory,&lt;br&gt;
in a fixed-width column, in an embedded system without a compressor — that is&lt;br&gt;
what you get, every time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compression eats much of the advantage.&lt;/strong&gt; UTF-8's repeated 3-byte lead bytes&lt;br&gt;
are precisely the redundancy gzip and brotli exist to remove, so a large part&lt;br&gt;
of what UCE-8 removes by design, a compressor removes anyway. Hindi's 30.8%&lt;br&gt;
becomes 9.3% under gzip.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On long compressed Chinese prose, UCE-8 can lose.&lt;/strong&gt; Measured across&lt;br&gt;
documents from 121 to 12,199 characters, brotli-compressed UCE-8 came out&lt;br&gt;
about &lt;strong&gt;2% larger&lt;/strong&gt; than brotli-compressed UTF-8 — stably, at every length.&lt;br&gt;
Brotli models UTF-8's regular structure better than it models UCE-8's.&lt;/p&gt;

&lt;p&gt;So the defensible claim is narrower than "33% for everyone," and it is still a&lt;br&gt;
real one: UCE-8 wins clearly on uncompressed text, and wins on compressed CJK,&lt;br&gt;
where the frequency-ordered index pages do information-theoretic work a&lt;br&gt;
general-purpose compressor cannot replicate.&lt;/p&gt;
&lt;h2&gt;
  
  
  Who it helps
&lt;/h2&gt;

&lt;p&gt;These scripts all sit in UTF-8's 3-byte range (U+0800–U+FFFF). "Page" is the&lt;br&gt;
page index — page &lt;code&gt;090&lt;/code&gt; is U+0900–U+097F.&lt;/p&gt;

&lt;p&gt;Every page's address is a plain ASCII byte, so the whole page map fits in one&lt;br&gt;
ASCII table — row is the high nibble, column the low nibble. Under each row of&lt;br&gt;
pages is the ASCII character that byte actually is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
  0  ·   ·   ·   ·   ·   ·   ·   ·   ·   ·   ·   ·   ·   ·   ·   ·
  1  ·   ·   ·   ·   ·   ·   ·   ·   ·   ·   ·   ·   ·   ·   ·   ·
  2  ·  008  ·   ·   ·   ·   ·   ·  010 038  ·   ·   ·   ·   ·   ·
     ␠   !   "   #   $   %   &amp;amp;   '   (   )   *   +   ,   -   .   /
  3 040 050 058 060 068 090 098 0A0 0A8 0B0  ·   ·   ·   ·   ·   ·
     0   1   2   3   4   5   6   7   8   9   :   ;   &amp;lt;   =   &amp;gt;   ?
  4  ·  0C0 0C8 0D0 0D8 0E0 0E8 0F0 100 120 128 130 178 1E8 300 308
     @   A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
  5 WLD WLD 4E0 4E8 540 5B8 628 7E8 8B8 8D0 CHN  ·   ·   ·  CHN CHN
     P   Q   R   S   T   U   V   W   X   Y   Z   [   \   ]   ^   _
  6  ·  CHN CHN CHN CHN CHN CHN CHN CHN CHN CHN CHN CHN CHN CHN CHN
     `   a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
  7 CHN CHN CHN CHN CHN CHN KOR KOR KOR KOR KOR  ·   ·   ·  KOR  ·
     p   q   r   s   t   u   v   w   x   y   z   {   |   }   ~   ␡
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rows 0 and 1 are the 32 control codes, which is why nothing is printable there.&lt;br&gt;
&lt;code&gt;·&lt;/code&gt; marks a value that can never be a page index — those plus the structural&lt;br&gt;
punctuation are the 60 exclusions. &lt;code&gt;WLD&lt;/code&gt; / &lt;code&gt;CHN&lt;/code&gt; / &lt;code&gt;KOR&lt;/code&gt; are indexed pages: a&lt;br&gt;
curated 128-entry list rather than an aligned Unicode block. What is left is&lt;br&gt;
&lt;strong&gt;68 usable pages × 128 = 8,704 characters&lt;/strong&gt; in two bytes.&lt;/p&gt;

&lt;p&gt;Devanagari sits at row 3, column 5 — ASCII &lt;code&gt;5&lt;/code&gt;. That is why &lt;code&gt;नमस्ते&lt;/code&gt; encodes&lt;br&gt;
full of the digit 5.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Page&lt;/th&gt;
&lt;th&gt;Script&lt;/th&gt;
&lt;th&gt;Unicode block&lt;/th&gt;
&lt;th&gt;Speakers (M)&lt;/th&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;090&lt;/td&gt;
&lt;td&gt;Devanagari&lt;/td&gt;
&lt;td&gt;U+0900–U+097F&lt;/td&gt;
&lt;td&gt;600.0&lt;/td&gt;
&lt;td&gt;full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;098&lt;/td&gt;
&lt;td&gt;Bengali&lt;/td&gt;
&lt;td&gt;U+0980–U+09FF&lt;/td&gt;
&lt;td&gt;284.0&lt;/td&gt;
&lt;td&gt;full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0A0&lt;/td&gt;
&lt;td&gt;Gurmukhi&lt;/td&gt;
&lt;td&gt;U+0A00–U+0A7F&lt;/td&gt;
&lt;td&gt;30.0&lt;/td&gt;
&lt;td&gt;full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0A8&lt;/td&gt;
&lt;td&gt;Gujarati&lt;/td&gt;
&lt;td&gt;U+0A80–U+0AFF&lt;/td&gt;
&lt;td&gt;57.0&lt;/td&gt;
&lt;td&gt;full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0B0&lt;/td&gt;
&lt;td&gt;Oriya&lt;/td&gt;
&lt;td&gt;U+0B00–U+0B7F&lt;/td&gt;
&lt;td&gt;41.0&lt;/td&gt;
&lt;td&gt;full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0B8&lt;/td&gt;
&lt;td&gt;Tamil&lt;/td&gt;
&lt;td&gt;U+0B80–U+0BFF&lt;/td&gt;
&lt;td&gt;78.0&lt;/td&gt;
&lt;td&gt;full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0C0&lt;/td&gt;
&lt;td&gt;Telugu&lt;/td&gt;
&lt;td&gt;U+0C00–U+0C7F&lt;/td&gt;
&lt;td&gt;83.0&lt;/td&gt;
&lt;td&gt;full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0C8&lt;/td&gt;
&lt;td&gt;Kannada&lt;/td&gt;
&lt;td&gt;U+0C80–U+0CFF&lt;/td&gt;
&lt;td&gt;43.0&lt;/td&gt;
&lt;td&gt;full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0D0&lt;/td&gt;
&lt;td&gt;Malayalam&lt;/td&gt;
&lt;td&gt;U+0D00–U+0D7F&lt;/td&gt;
&lt;td&gt;45.0&lt;/td&gt;
&lt;td&gt;full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0D8&lt;/td&gt;
&lt;td&gt;Sinhala&lt;/td&gt;
&lt;td&gt;U+0D80–U+0DFF&lt;/td&gt;
&lt;td&gt;17.0&lt;/td&gt;
&lt;td&gt;full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0E0&lt;/td&gt;
&lt;td&gt;Thai&lt;/td&gt;
&lt;td&gt;U+0E00–U+0E7F&lt;/td&gt;
&lt;td&gt;71.0&lt;/td&gt;
&lt;td&gt;full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0E8&lt;/td&gt;
&lt;td&gt;Lao&lt;/td&gt;
&lt;td&gt;U+0E80–U+0EFF&lt;/td&gt;
&lt;td&gt;7.7&lt;/td&gt;
&lt;td&gt;full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0F0&lt;/td&gt;
&lt;td&gt;Tibetan&lt;/td&gt;
&lt;td&gt;U+0F00–U+0FFF&lt;/td&gt;
&lt;td&gt;6.0&lt;/td&gt;
&lt;td&gt;full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;Myanmar&lt;/td&gt;
&lt;td&gt;U+1000–U+109F&lt;/td&gt;
&lt;td&gt;33.0&lt;/td&gt;
&lt;td&gt;full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;108&lt;/td&gt;
&lt;td&gt;Georgian&lt;/td&gt;
&lt;td&gt;U+10A0–U+10FF&lt;/td&gt;
&lt;td&gt;3.6&lt;/td&gt;
&lt;td&gt;full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;120&lt;/td&gt;
&lt;td&gt;Ethiopic&lt;/td&gt;
&lt;td&gt;U+1200–U+137F&lt;/td&gt;
&lt;td&gt;135.0&lt;/td&gt;
&lt;td&gt;full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;178&lt;/td&gt;
&lt;td&gt;Khmer&lt;/td&gt;
&lt;td&gt;U+1780–U+17FF&lt;/td&gt;
&lt;td&gt;18.0&lt;/td&gt;
&lt;td&gt;full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;180&lt;/td&gt;
&lt;td&gt;Mongolian&lt;/td&gt;
&lt;td&gt;U+1800–U+18AF&lt;/td&gt;
&lt;td&gt;10.0&lt;/td&gt;
&lt;td&gt;traditional script — 27.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1E8&lt;/td&gt;
&lt;td&gt;Vietnamese&lt;/td&gt;
&lt;td&gt;U+1E00–U+1EFF&lt;/td&gt;
&lt;td&gt;86.0&lt;/td&gt;
&lt;td&gt;8.1% — page shared with Yoruba, Igbo, Welsh&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;300&lt;/td&gt;
&lt;td&gt;Japanese&lt;/td&gt;
&lt;td&gt;U+3040–U+30FF&lt;/td&gt;
&lt;td&gt;122.0&lt;/td&gt;
&lt;td&gt;30.7% — kana full, kanji partial&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4E0&lt;/td&gt;
&lt;td&gt;Chinese&lt;/td&gt;
&lt;td&gt;U+4E00–U+9FFF&lt;/td&gt;
&lt;td&gt;1,400.0&lt;/td&gt;
&lt;td&gt;full — simplified; traditional 27.2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AC0&lt;/td&gt;
&lt;td&gt;Korean&lt;/td&gt;
&lt;td&gt;U+AC00–U+D7A3&lt;/td&gt;
&lt;td&gt;78.0&lt;/td&gt;
&lt;td&gt;full — 89% of running text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3,248.3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That is roughly &lt;strong&gt;3.2 billion people&lt;/strong&gt; whose everyday writing drops from 3&lt;br&gt;
bytes per character to 2.&lt;/p&gt;
&lt;h3&gt;
  
  
  How much each one actually gains
&lt;/h3&gt;

&lt;p&gt;Every figure below is measured, not estimated. Most of the table gains the&lt;br&gt;
full 3→2 bytes; five entries gain less, and they are worth knowing about&lt;br&gt;
before anyone else finds them:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Script&lt;/th&gt;
&lt;th&gt;Measured&lt;/th&gt;
&lt;th&gt;Why it differs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Japanese&lt;/td&gt;
&lt;td&gt;30.7%&lt;/td&gt;
&lt;td&gt;Kana and CJK punctuation have dedicated pages; kanji coverage is incidental — 19 of 38 common kanji tested still cost 3 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chinese (traditional)&lt;/td&gt;
&lt;td&gt;27.2%&lt;/td&gt;
&lt;td&gt;The index is simplified-only; 28 of 39 common Traditional characters tested fall to tier 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mongolian (traditional)&lt;/td&gt;
&lt;td&gt;27.0%&lt;/td&gt;
&lt;td&gt;32 curated characters of the traditional script&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vietnamese&lt;/td&gt;
&lt;td&gt;8.1%&lt;/td&gt;
&lt;td&gt;Mostly plain ASCII Latin already — only the diacritic characters were ever 3-byte&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mongolian (Cyrillic)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.0%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cyrillic is 2 bytes in UTF-8 &lt;em&gt;and&lt;/em&gt; 2 bytes in UCE-8 — unchanged&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The Mongolian split is the one to keep straight: Mongolia writes in Cyrillic,&lt;br&gt;
which UCE-8 leaves exactly the same size. The 27% gain belongs to the&lt;br&gt;
traditional script, used mainly in Inner Mongolia. Counting all 10 million&lt;br&gt;
Mongolian speakers as beneficiaries of the traditional-script pages overstates&lt;br&gt;
the case, and it is the first thing a careful reader will check.&lt;/p&gt;
&lt;h2&gt;
  
  
  What it costs
&lt;/h2&gt;

&lt;p&gt;UCE-8 is not a drop-in, and the case for it is only credible if the costs are&lt;br&gt;
stated alongside the savings.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It is not UTF-8.&lt;/strong&gt; A UCE-8 stream is not valid UTF-8 and a UTF-8 stream is
not valid UCE-8. Every reader, editor, database, terminal and library in the
path needs to know which one it is holding. This is an ecosystem break, not
an upgrade.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Byte order is not code-point order.&lt;/strong&gt; The indexed pages are ordered by
frequency, so sorting encoded bytes does not sort characters. Binary search,
range queries and index ordering over raw UCE-8 all change meaning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Naive matching breaks&lt;/strong&gt;, as shown above — trail bytes are ordinary ASCII
digits and letters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compression narrows the win&lt;/strong&gt;, and for long brotli-compressed Chinese
reverses it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coverage is a frozen guess.&lt;/strong&gt; &lt;code&gt;CHINESE_CHARS&lt;/code&gt;, &lt;code&gt;KOREAN_CHARS&lt;/code&gt; and
&lt;code&gt;WORLD_CHARS&lt;/code&gt; cannot be reordered without changing the meaning of every
byte sequence ever written. Whatever the frequency tables got wrong is
permanent.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Reference implementation
&lt;/h2&gt;

&lt;p&gt;The whole encoder is three branches and a fallback. &lt;code&gt;LEAD_BASE&lt;/code&gt; is &lt;code&gt;0x80&lt;/code&gt; —&lt;br&gt;
setting the high bit marks a byte as "more follows". &lt;code&gt;TAIL_COUNT&lt;/code&gt; is 68, the&lt;br&gt;
number of usable trail values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code_point&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Encode a Unicode code point into 1, 2 or 3 bytes.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;code_point&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;handle_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Negative code point&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;code_point&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;MAX_CODE_POINT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;handle_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Beyond the Unicode range&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# TIER 1 - plain ascii passes straight through
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;code_point&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;code_point&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="c1"&gt;# TIER 2a - block pages: world scripts and the 8 Chinese blocks
&lt;/span&gt;    &lt;span class="n"&gt;trail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PAGE_TO_TRAIL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;code_point&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;trail&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;LEAD_BASE&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code_point&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x7F&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;trail&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="c1"&gt;# TIER 2b - indexed Chinese
&lt;/span&gt;    &lt;span class="n"&gt;slot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CHINESE_SLOT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code_point&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;slot&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;LEAD_BASE&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slot&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x7F&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;CHINESE_TRAILS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;slot&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;

    &lt;span class="c1"&gt;# TIER 2c - indexed Korean
&lt;/span&gt;    &lt;span class="n"&gt;slot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;KOREAN_SLOT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code_point&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;slot&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;LEAD_BASE&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slot&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x7F&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;KOREAN_TRAILS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;slot&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;

    &lt;span class="c1"&gt;# TIER 2d - indexed world pages
&lt;/span&gt;    &lt;span class="n"&gt;slot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WORLD_SLOT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code_point&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;slot&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;LEAD_BASE&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slot&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x7F&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;WORLD_TRAILS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;slot&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;

    &lt;span class="c1"&gt;# TIER 3 - everything else
&lt;/span&gt;    &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;code_point&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;
    &lt;span class="n"&gt;tail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;TAIL_COUNT&lt;/span&gt;
    &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;TAIL_COUNT&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="n"&gt;LEAD_BASE&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;LEAD_BASE&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x7F&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;TAIL_BYTES&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Decoding reads the high bit of the second byte to pick the tier, then the&lt;br&gt;
trail byte to pick the page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Decode a 1, 2 or 3 byte sequence back into a Unicode code point.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;

    &lt;span class="n"&gt;second&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# TIER 2 - second byte clears the high bit, so it terminates
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TRAIL_TO_PAGE&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;handle_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Trail byte is not a page index&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;WORLD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;WORLD_CODE_POINTS&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;WORLD_PAGE&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x7F&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;CHINESE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;CHINESE_CODE_POINTS&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;CHINESE_PAGE&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x7F&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;KOREAN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;KOREAN_CODE_POINTS&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;KOREAN_PAGE&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x7F&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

        &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x7F&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# TIER 3 - second byte keeps the high bit, a third follows
&lt;/span&gt;    &lt;span class="n"&gt;tail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TAIL_INDEX&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;handle_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Third byte is not a legal terminating value&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x7F&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x7F&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;TAIL_COUNT&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Encoding a whole string is a &lt;code&gt;join&lt;/code&gt;, since every character is independent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;uce8_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note what tier 3 does differently. Tiers 1 and 2 map a code point to a &lt;em&gt;page&lt;br&gt;
and slot&lt;/em&gt;; tier 3 has no page table left, so it spreads the remaining code&lt;br&gt;
points across the 68 legal trail values arithmetically — &lt;code&gt;index % TAIL_COUNT&lt;/code&gt;&lt;br&gt;
picks the terminator, &lt;code&gt;index // TAIL_COUNT&lt;/code&gt; becomes the two lead bytes. That&lt;br&gt;
is why tier 3's capacity is exactly 128 × 128 × 68, and why the encoding never&lt;br&gt;
emits an illegal terminator even in its fallback path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Status
&lt;/h2&gt;

&lt;p&gt;UCE-8 is an experimental encoding, not a deployed standard.&lt;/p&gt;

&lt;p&gt;Full source: &lt;strong&gt;&lt;a href="https://gitlab.com/eric.shagdarjav/uce" rel="noopener noreferrer"&gt;https://gitlab.com/eric.shagdarjav/uce&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://gitlab.com/eric.shagdarjav/uce/-/blob/main/uce_hibrid.py" rel="noopener noreferrer"&gt;uce_hibrid.py&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Reference implementation — encoder, decoder, frozen character tables&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://gitlab.com/eric.shagdarjav/uce/-/blob/main/docs/verify.py" rel="noopener noreferrer"&gt;verify.py&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Reproduces every figure in this article&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://gitlab.com/eric.shagdarjav/uce/-/blob/main/index.html" rel="noopener noreferrer"&gt;index.html&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Interactive demo — runs the real tables in the browser&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;uce_hibrid.py&lt;/code&gt; has no dependencies beyond the Python standard library. Run it&lt;br&gt;
directly for the built-in test vectors, or &lt;code&gt;python3 docs/verify.py&lt;/code&gt; to&lt;br&gt;
reproduce every number here.&lt;/p&gt;

</description>
      <category>unicode</category>
      <category>python</category>
      <category>programming</category>
      <category>performance</category>
    </item>
  </channel>
</rss>
