|
|
sethmlarson.dev_werkzeug.atom.xml - sfeed_tests - sfeed tests and RSS and Atom files |
|
|
 |
git clone git://git.codemadness.org/sfeed_tests (git://git.codemadness.org) |
|
|
 |
Log |
|
|
 |
Files |
|
|
 |
Refs |
|
|
 |
README |
|
|
 |
LICENSE |
|
|
|
--- |
|
|
|
sethmlarson.dev_werkzeug.atom.xml (458966B) |
|
|
|
--- |
|
|
|
1 <?xml version="1.0" encoding="utf-8"?> |
|
|
|
2 <feed xmlns="http://www.w3.org/2005/Atom"> |
|
|
|
3 <title type="text">sethmlarson.dev - Last 5 Blog Posts</title> |
|
|
|
4 <id>http://sethmlarson.dev/feed</id> |
|
|
|
5 <updated>2022-02-08T00:00:00Z</updated> |
|
|
|
6 <link href="http://sethmlarson.dev/" /> |
|
|
|
7 <link href="http://sethmlarson.dev/feed" rel="self" /> |
|
|
|
8 <generator>Werkzeug</generator> |
|
|
|
9 <entry xml:base="http://sethmlarson.dev/feed"> |
|
|
|
10 <title type="text">How does UTF-8 turn βπβ into βF09F9882β?</title> |
|
|
|
11 <id>http://sethmlarson.dev/blog/utf-8?date=2022-02-08</id> |
|
|
|
12 <updated>2022-02-08T00:00:00Z</updated> |
|
|
|
13 <published>2022-02-08T00:00:00Z</published> |
|
|
|
14 <link href="http://sethmlarson.dev/blog/utf-8?date=2022-02-08" /> |
|
|
|
15 <author> |
|
|
|
16 <name>Seth Michael Larson</name> |
|
|
|
17 </author> |
|
|
|
18 <content type="html"><!DOCTYPE html> |
|
|
|
19 <html lang="en"> |
|
|
|
20 <head> |
|
|
|
21 <meta charset="utf-8"> |
|
|
|
22 <title>How does UTF-8 turn βπβ into βF09F9882β?</title> |
|
|
|
23 <meta name="description" content="Blogging about Python and the Internet"> |
|
|
|
24 <meta name="keywords" content="blog python open source http networking security"> |
|
|
|
25 <meta name="author" content="Seth Michael Larson"> |
|
|
|
26 <meta name="viewport" content="width=device-width, initial-scale=1"> |
|
|
|
27 <meta name="format-detection" content="telephone=no"/> |
|
|
|
28 <link rel="alternate" type="application/rss+xml" title="RSS Feed" href="/feed"/> |
|
|
|
29 <link rel="icon" href="/static/favicon.ico"> |
|
|
|
30 <link rel="stylesheet" href="/static/style.css"> |
|
|
|
31 |
|
|
|
32 <meta property="og:site_name" content="Seth Michael Larson"/> |
|
|
|
33 <meta property="og:author" content="Seth Michael Larson"/> |
|
|
|
34 <meta property="og:type" content="article"/> |
|
|
|
35 <meta property="og:title" content="How does UTF-8 turn βπβ into βF09F9882β?"/> |
|
|
|
36 <meta property="og:description" content="If you&#39;re anything like me, you love emojis! Emojis appear like an image on the screen, but they aren&#39;t an image like a PNG or JPEG. What do emojis look like to computers? |
|
|
|
37 |
|
|
|
38 |
|
|
|
39 &amp;#xa;&amp;#xa;0x820x820x980..."/> |
|
|
|
40 <meta property="og:image" content="http://sethmlarson.dev/static/avatar.jpeg"/> |
|
|
|
41 <meta name="twitter:card" content="summary"/> |
|
|
|
42 <meta name="twitter:site" content="@sethmlarson"/> |
|
|
|
43 <meta name="twitter:creator" content="@sethmlarson"/> |
|
|
|
44 <meta name="twitter:title" content="How does UTF-8 turn βπβ into βF09F9882β?"/> |
|
|
|
45 <meta name="twitter:description" content="If you&#39;re anything like me, you love emojis! Emojis appear like an image on the screen, but they aren&#39;t an image like a PNG or JPEG. What do emojis look like to computers? |
|
|
|
46 |
|
|
|
47 |
|
|
|
48 &amp;#xa;&amp;#xa;0x820x820x980..."/> |
|
|
|
49 <meta property="og:image" content="http://sethmlarson.dev/static/avatar.jpeg"/> |
|
|
|
50 |
|
|
|
51 </head> |
|
|
|
52 <body> |
|
|
|
53 <div class="container"> |
|
|
|
54 <div class="row"> |
|
|
|
55 <div class="col-6"> |
|
|
|
56 <center> |
|
|
|
57 <h1 style="margin-bottom: 0.1em; font-size: 1.8em;">Seth Michael Larson</h1> |
|
|
|
58 <span style="font-style: italic;">Blogging about Python and the Internet</span> |
|
|
|
59 </center> |
|
|
|
60 </div> |
|
|
|
61 <div class="col-6"> |
|
|
|
62 <div class="navbar-outer"> |
|
|
|
63 <div class="navbar-inner"> |
|
|
|
64 <a class="icon" href="/about"> |
|
|
|
65 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"> |
|
|
|
66 <title>About</title><path d="M528 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h480c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-352 96c35.3 0 64 28.7 64 64s-28.7 64-64 64-64-28.7-64-64 28.7-64 64-64zm112 236.8c0 10.6-10 19.2-22.4 19.2H86.4C74 384 64 375.4 64 364.8v-19.2c0-31.8 30.1-57.6 67.2-57.6h5c12.3 5.1 25.7 8 39.8 8s27.6-2.9 39.8-8h5c37.1 0 67.2 25.8 67.2 57.6v19.2zM512 312c0 4.4-3.6 8-8 8H360c-4.4 0-8-3.6-8-8v-16c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16zm0-64c0 4.4-3.6 8-8 8H360c-4.4 0-8-3.6-8-8v-16c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16zm0-64c0 4.4-3.6 8-8 8H360c-4.4 0-8-3.6-8-8v-16c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16z"/> |
|
|
|
67 </svg> |
|
|
|
68 </a> |
|
|
|
69 <a class="icon" href="/blog"> |
|
|
|
70 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> |
|
|
|
71 <title>Blog</title><path d="M172.2 226.8c-14.6-2.9-28.2 8.9-28.2 23.8V301c0 10.2 7.1 18.4 16.7 22 18.2 6.8 31.3 24.4 31.3 45 0 26.5-21.5 48-48 48s-48-21.5-48-48V120c0-13.3-10.7-24-24-24H24c-13.3 0-24 10.7-24 24v248c0 89.5 82.1 160.2 175 140.7 54.4-11.4 98.3-55.4 109.7-109.7 17.4-82.9-37-157.2-112.5-172.2zM209 0c-9.2-.5-17 6.8-17 16v31.6c0 8.5 6.6 15.5 15 15.9 129.4 7 233.4 112 240.9 241.5.5 8.4 7.5 15 15.9 15h32.1c9.2 0 16.5-7.8 16-17C503.4 139.8 372.2 8.6 209 0zm.3 96c-9.3-.7-17.3 6.7-17.3 16.1v32.1c0 8.4 6.5 15.3 14.8 15.9 76.8 6.3 138 68.2 144.9 145.2.8 8.3 7.6 14.7 15.9 14.7h32.2c9.3 0 16.8-8 16.1-17.3-8.4-110.1-96.5-198.2-206.6-206.7z"/> |
|
|
|
72 </svg> |
|
|
|
73 </a> |
|
|
|
74 <a class="icon" href="https://twitter.com/sethmlarson" target="_blank" rel="nofollow noopener noreferrer"> |
|
|
|
75 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> |
|
|
|
76 <title>Twitter</title><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/> |
|
|
|
77 </svg> |
|
|
|
78 </a> |
|
|
|
79 <a class="icon" href="https://github.com/sethmlarson" target="_blank" rel="nofollow noopener noreferrer"> |
|
|
|
80 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"> |
|
|
|
81 <title>GitHub</title><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/> |
|
|
|
82 </svg> |
|
|
|
83 </a> |
|
|
|
84 <a class="icon" href="https://linkedin.com/in/sethmlarson" target="_blank" rel="nofollow noopener noreferrer"> |
|
|
|
85 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"> |
|
|
|
86 <title>LinkedIn</title><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3zM135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5zm282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9V416z"/> |
|
|
|
87 </svg> |
|
|
|
88 </a> |
|
|
|
89 </div> |
|
|
|
90 </div> |
|
|
|
91 </div> |
|
|
|
92 </div> |
|
|
|
93 |
|
|
|
94 <div class="row"> |
|
|
|
95 <div class="col-12"> |
|
|
|
96 <h2 class="blog-title" style="text-align: center">How does UTF-8 turn βπβ into βF09F9882β?</h2> |
|
|
|
97 <p><center>Published 2022-02-08 β <span class="heart">β€&#xFE0E</span> Subscribe for more via <a href="https://tinyletter.com/sethmlarson">the newsletter</a> or <a href="/feed">RSS</a></center></p> |
|
|
|
98 </div> |
|
|
|
99 </div> |
|
|
|
100 <div class="row"> |
|
|
|
101 <div class="col-12"> |
|
|
|
102 <p>If you're anything like me, you love emojis! Emojis appear like an image on the screen, but they aren't an image like a PNG or JPEG. <strong>What do emojis look like to computers?</strong></p> |
|
|
|
103 |
|
|
|
104 <p><center> |
|
|
|
105 <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="561px" viewBox="-0.5 -0.5 561 121" style="max-width:100%;max-height:121px;"><defs/><g><rect x="0" y="0" width="120" height="120" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 7 60)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 60px; margin-left: -52px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><div><br /></div><div><br /></div></div></div></div></foreignObject><text x="7" y="80" fill="#333333" font-family="monospace" font-size="20px" text-anchor="middle">&#xa;</text></switch></g><rect x="280" y="0" width="280" height="120" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 287 60)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 60px; margin-left: 228px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><div><br /></div><div><br /></div></div></div></div></foreignObject><text x="287" y="80" fill="#333333" font-family="monospace" font-size="20px" text-anchor="middle">&#xa;</text></switch></g><rect x="480" y="20" width="60" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 60px; margin-left: 481px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>82</div></div></div></foreignObject><text x="510" y="66" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0x82</text></switch></g><rect x="420" y="20" width="60" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 60px; margin-left: 421px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>98</div></div></div></foreignObject><text x="450" y="66" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0x98</text></switch></g><rect x="360" y="20" width="60" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 60px; margin-left: 361px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>9F</div></div></div></foreignObject><text x="390" y="66" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0x9F</text></switch></g><rect x="300" y="20" width="60" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 60px; margin-left: 301px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>F0</div></div></div></foreignObject><text x="330" y="66" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0xF0</text></switch></g><rect x="20" y="20" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 60px; margin-left: 21px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font style="font-size: 36px">π</font></div></div></div></foreignObject><text x="60" y="64" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">π</text></switch></g><rect x="140" y="0" width="120" height="120" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 147 60)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 60px; margin-left: 88px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><div><br /></div><div><br /></div></div></div></div></foreignObject><text x="147" y="80" fill="#333333" font-family="monospace" font-size="20px" text-anchor="middle">&#xa;</text></switch></g><rect x="160" y="20" width="80" height="80" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 60px; margin-left: 161px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font style="font-size: 24px">???</font></div></div></div></foreignObject><text x="200" y="64" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">???</text></switch></g><path d="M 100 60 L 153.63 60" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 158.88 60 L 151.88 63.5 L 153.63 60 L 151.88 56.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 240 60 L 293.63 60" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 298.88 60 L 291.88 63.5 L 293.63 60 L 291.88 56.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> |
|
|
|
106 </center></p> |
|
|
|
107 |
|
|
|
108 <p><strong><a href="https://w3techs.com/technologies/overview/character_encoding">More often than not</a> the mechanism being used to turn bytes into characters and emojis on your computer is "UTF-8"</strong>.</p> |
|
|
|
109 |
|
|
|
110 <p>I recently learned how UTF-8 works and felt that the definition lended itself perfectly to creating diagrams explaining the implementation. I created these diagrams for my own enjoyment and wanted to share them. Hopefully this will inspire you to learn how other low-level protocols work too! <a href="https://github.com/sethmlarson/utf-8-diagrams">All diagrams are available on GitHub</a>.</p> |
|
|
|
111 |
|
|
|
112 <h2>What is UTF-8?</h2> |
|
|
|
113 |
|
|
|
114 <p>UTF-8 is an encoding currently defined in <a href="https://www.rfc-editor.org/rfc/rfc3629.html">RFC 3629</a> (<a href="https://www.rfc-editor.org/rfc/rfc2044.html">first published in 1996 in RFC 2044</a>) describes encoding Unicode characters into bytes. Unicode uses a concept called a "<a href="https://en.wikipedia.org/wiki/Code_point">codepoint</a>" which is essentially a number that maps to a single "character" within the Unicode standard. Unicode codepoints are often written as hex with a <code>U+</code> prefix. For example, the character "π" is codepoint <code>0x1F602</code> (128,514 in decimal) and would be written as <code>U+1F602</code>.</p> |
|
|
|
115 |
|
|
|
116 <div class="row"> |
|
|
|
117 <div class="col-6"> |
|
|
|
118 |
|
|
|
119 <h2>The 5 octets of UTF-8</h2> |
|
|
|
120 |
|
|
|
121 <blockquote> |
|
|
|
122 <p><strong>NOTE:</strong> I use the term "octet" in this article which means "a grouping of 8 bits". Today's computers consider 8 bits to be 1 byte, but previously there were systems which used a different number of bits per "byte" hence the distinction. For our purposes an octet and a byte are the same thing.</p> |
|
|
|
123 </blockquote> |
|
|
|
124 |
|
|
|
125 <p> |
|
|
|
126 Every octet that can be produced using UTF-8 will fall into one of five types. The octet will either be a "header" octet specifying a length of 1, 2, 3, or 4 octets or a "tail" octet which only holds onto data. You can determine what type each individual octet is by examining the high-order bits (in this representation these bits are left-most in a block and colored green). |
|
|
|
127 </p> |
|
|
|
128 |
|
|
|
129 <p> |
|
|
|
130 Each octet also has "empty" spaces for bits (visualized as <code>X</code> in blue) which we'll eventually fill with data. You can also see the 4 unique layouts that a UTF-8 encoded codepoint can use to store different amounts of data (between 7-21 bits). |
|
|
|
131 </p> |
|
|
|
132 |
|
|
|
133 </div> |
|
|
|
134 |
|
|
|
135 <div class="col-6"> |
|
|
|
136 |
|
|
|
137 <center> |
|
|
|
138 <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="391px" viewBox="-0.5 -0.5 391 621" style="max-width:100%;max-height:621px;"><defs/><g><rect x="0" y="0" width="390" height="340" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 7 170)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 338px; height: 1px; padding-top: 170px; margin-left: -162px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">UTF-8 OCTETS</div></div></div></foreignObject><text x="7" y="190" fill="#333333" font-family="monospace" font-size="20px" text-anchor="middle">UTF-8 OCTETS</text></switch></g><rect x="40" y="0" width="350" height="260" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 47 130)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 258px; height: 1px; padding-top: 130px; margin-left: -82px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">UTF-8 HEADER OCTETS</div></div></div></foreignObject><text x="47" y="150" fill="#333333" font-family="monospace" font-size="20px" text-anchor="middle">UTF-8 HEADER OCTETS</text></switch></g><rect x="90" y="20" width="10" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 8px; height: 1px; padding-top: 40px; margin-left: 91px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">0</div></div></div></foreignObject><text x="95" y="44" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">0</text></switch></g><rect x="90" y="80" width="30" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 100px; margin-left: 91px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">110</div></div></div></foreignObject><text x="105" y="104" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">110</text></switch></g><rect x="90" y="140" width="40" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 38px; height: 1px; padding-top: 160px; margin-left: 91px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">1110</div></div></div></foreignObject><text x="110" y="164" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">1110</text></switch></g><rect x="90" y="200" width="50" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 48px; height: 1px; padding-top: 220px; margin-left: 91px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">11110</div></div></div></foreignObject><text x="115" y="224" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">11110</text></switch></g><rect x="100" y="20" width="70" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 40px; margin-left: 101px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">xxxxxxx</div></div></div></foreignObject><text x="135" y="44" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">xxxxxxx</text></switch></g><rect x="120" y="80" width="50" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 48px; height: 1px; padding-top: 100px; margin-left: 121px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">xxxxx</div></div></div></foreignObject><text x="145" y="104" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">xxxxx</text></switch></g><rect x="130" y="140" width="40" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 38px; height: 1px; padding-top: 160px; margin-left: 131px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">xxxx</div></div></div></foreignObject><text x="150" y="164" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">xxxx</text></switch></g><rect x="140" y="200" width="30" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 220px; margin-left: 141px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">xxx</div></div></div></foreignObject><text x="155" y="224" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">xxx</text></switch></g><rect x="90" y="280" width="20" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 18px; height: 1px; padding-top: 300px; margin-left: 91px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10</div></div></div></foreignObject><text x="100" y="304" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10</text></switch></g><rect x="110" y="280" width="60" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 300px; margin-left: 111px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">xxxxxx</div></div></div></foreignObject><text x="140" y="304" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">xxxxxx</text></switch></g><rect x="180" y="20" width="170" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 168px; height: 1px; padding-top: 40px; margin-left: 182px;"><div style="box-sizing: border-box; font-size: 0px; text-align: left;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 16px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">U+0000βU+007F<br />1 octet header</div></div></div></foreignObject><text x="182" y="45" fill="rgb(0, 0, 0)" font-family="monospace" font-size="16px">U+0000βU+007F...</text></switch></g><rect x="180" y="80" width="170" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 168px; height: 1px; padding-top: 100px; margin-left: 182px;"><div style="box-sizing: border-box; font-size: 0px; text-align: left;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 16px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">U+0080βU+07FF<br />2 octet header</div></div></div></foreignObject><text x="182" y="105" fill="rgb(0, 0, 0)" font-family="monospace" font-size="16px">U+0080βU+07FF...</text></switch></g><rect x="180" y="140" width="170" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 168px; height: 1px; padding-top: 160px; margin-left: 182px;"><div style="box-sizing: border-box; font-size: 0px; text-align: left;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 16px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">U+0800βU+FFFF<br />3 octet header</div></div></div></foreignObject><text x="182" y="165" fill="rgb(0, 0, 0)" font-family="monospace" font-size="16px">U+0800βU+FFFF...</text></switch></g><rect x="180" y="200" width="170" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 168px; height: 1px; padding-top: 220px; margin-left: 182px;"><div style="box-sizing: border-box; font-size: 0px; text-align: left;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 16px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><div>U+10000βU+10FFFF<br />4 octet header<br /></div></div></div></div></foreignObject><text x="182" y="225" fill="rgb(0, 0, 0)" font-family="monospace" font-size="16px">U+10000βU+10FFFF...</text></switch></g><rect x="180" y="280" width="170" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 168px; height: 1px; padding-top: 300px; margin-left: 182px;"><div style="box-sizing: border-box; font-size: 0px; text-align: left;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 16px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Tail/data octet</div></div></div></foreignObject><text x="182" y="305" fill="rgb(0, 0, 0)" font-family="monospace" font-size="16px">Tail/data octet</text></switch></g><rect x="0" y="360" width="390" height="260" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><rect x="10" y="380" width="10" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 8px; height: 1px; padding-top: 400px; margin-left: 11px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">0</div></div></div></foreignObject><text x="15" y="404" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">0</text></switch></g><rect x="10" y="440" width="30" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 460px; margin-left: 11px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">110</div></div></div></foreignObject><text x="25" y="464" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">110</text></switch></g><rect x="10" y="500" width="40" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 38px; height: 1px; padding-top: 520px; margin-left: 11px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">1110</div></div></div></foreignObject><text x="30" y="524" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">1110</text></switch></g><rect x="10" y="560" width="50" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 48px; height: 1px; padding-top: 580px; margin-left: 11px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">11110</div></div></div></foreignObject><text x="35" y="584" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">11110</text></switch></g><rect x="20" y="380" width="70" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 400px; margin-left: 21px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">xxxxxxx</div></div></div></foreignObject><text x="55" y="404" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">xxxxxxx</text></switch></g><rect x="40" y="440" width="50" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 48px; height: 1px; padding-top: 460px; margin-left: 41px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">xxxxx</div></div></div></foreignObject><text x="65" y="464" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">xxxxx</text></switch></g><rect x="50" y="500" width="40" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 38px; height: 1px; padding-top: 520px; margin-left: 51px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">xxxx</div></div></div></foreignObject><text x="70" y="524" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">xxxx</text></switch></g><rect x="60" y="560" width="30" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 580px; margin-left: 61px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">xxx</div></div></div></foreignObject><text x="75" y="584" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">xxx</text></switch></g><rect x="90" y="440" width="20" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 18px; height: 1px; padding-top: 460px; margin-left: 91px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10</div></div></div></foreignObject><text x="100" y="464" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10</text></switch></g><rect x="110" y="440" width="60" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 460px; margin-left: 111px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">xxxxxx</div></div></div></foreignObject><text x="140" y="464" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">xxxxxx</text></switch></g><rect x="90" y="500" width="20" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 18px; height: 1px; padding-top: 520px; margin-left: 91px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10</div></div></div></foreignObject><text x="100" y="524" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10</text></switch></g><rect x="110" y="500" width="60" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 520px; margin-left: 111px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">xxxxxx</div></div></div></foreignObject><text x="140" y="524" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">xxxxxx</text></switch></g><rect x="90" y="560" width="20" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 18px; height: 1px; padding-top: 580px; margin-left: 91px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10</div></div></div></foreignObject><text x="100" y="584" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10</text></switch></g><rect x="110" y="560" width="60" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 580px; margin-left: 111px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">xxxxxx</div></div></div></foreignObject><text x="140" y="584" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">xxxxxx</text></switch></g><rect x="170" y="560" width="20" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 18px; height: 1px; padding-top: 580px; margin-left: 171px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10</div></div></div></foreignObject><text x="180" y="584" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10</text></switch></g><rect x="190" y="560" width="60" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 580px; margin-left: 191px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">xxxxxx</div></div></div></foreignObject><text x="220" y="584" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">xxxxxx</text></switch></g><rect x="250" y="560" width="20" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 18px; height: 1px; padding-top: 580px; margin-left: 251px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10</div></div></div></foreignObject><text x="260" y="584" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10</text></switch></g><rect x="270" y="560" width="60" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 580px; margin-left: 271px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">xxxxxx</div></div></div></foreignObject><text x="300" y="584" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">xxxxxx</text></switch></g><rect x="170" y="500" width="20" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 18px; height: 1px; padding-top: 520px; margin-left: 171px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10</div></div></div></foreignObject><text x="180" y="524" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10</text></switch></g><rect x="190" y="500" width="60" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 520px; margin-left: 191px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">xxxxxx</div></div></div></foreignObject><text x="220" y="524" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">xxxxxx</text></switch></g><rect x="330" y="560" width="60" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 580px; margin-left: 331px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font face="Courier New">21 data bits<br /></font></div></div></div></foreignObject><text x="360" y="584" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">21 data bi...</text></switch></g><rect x="170" y="440" width="60" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 460px; margin-left: 171px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font face="Courier New">11 data bits<br /></font></div></div></div></foreignObject><text x="200" y="464" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">11 data bi...</text></switch></g><rect x="250" y="500" width="60" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 520px; margin-left: 251px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font face="Courier New">16 data bits<br /></font></div></div></div></foreignObject><text x="280" y="524" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">16 data bi...</text></switch></g><rect x="90" y="380" width="60" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 400px; margin-left: 91px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font face="Courier New">7 data bits<br /></font></div></div></div></foreignObject><text x="120" y="404" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">7 data bit...</text></switch></g><rect x="240" y="370" width="140" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 138px; height: 1px; padding-top: 390px; margin-left: 241px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 16px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><div style="font-size: 19px" align="center"><font style="font-size: 19px">UTF-8 OCTET LAYOUTS</font></div></div></div></div></foreignObject><text x="310" y="395" fill="rgb(0, 0, 0)" font-family="monospace" font-size="16px" text-anchor="middle">UTF-8 OCTET LAYOU...</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> |
|
|
|
139 </center> |
|
|
|
140 |
|
|
|
141 </div> |
|
|
|
142 |
|
|
|
143 <p></div></p> |
|
|
|
144 |
|
|
|
145 <h2>What are bit prefixes?</h2> |
|
|
|
146 |
|
|
|
147 <p>Bit prefixes is a common technique that allows for encoding information while still leaving room in the octet for other information. Bit prefixing works by choosing a list of prefixes such that when each bit is read from left to right you eventually know unambiguously which prefix has been used.</p> |
|
|
|
148 |
|
|
|
149 <p><strong>Bit prefixing is useful to maximize the extra space on prefixes that are more commonly used.</strong></p> |
|
|
|
150 |
|
|
|
151 <p>In the case of UTF-8 the shortest prefixes are <code>0</code> and <code>10</code> where <code>10</code> is for the tail octet which is used between 1-3 times per characters for higher codepoint characters. The <code>0</code> prefix was likely selected more for its utility rather than its frequency when desiging UTF-8 to maintain compatibility with US-ASCII, more on this later!</p> |
|
|
|
152 |
|
|
|
153 <p>Looking at the prefixes for UTF-8 octets the possibilities are <code>0</code>, <code>10</code>, <code>110</code>, <code>1110</code>, and <code>11110</code>. If I start reading an octet from left to right and encounter the bits <code>1</code>, <code>1</code>, and <code>0</code> I immediately know without reading further that this octet is a "2 octet header" and can't possibly be any other octet type.</p> |
|
|
|
154 |
|
|
|
155 <div class="row"> |
|
|
|
156 <div class="col-6"> |
|
|
|
157 |
|
|
|
158 <h2>Following the flow of bits</h2> |
|
|
|
159 |
|
|
|
160 <p>Using Python we're able to see that our target output is <code>\xf0\x9f\x98\x82</code>:</p> |
|
|
|
161 |
|
|
|
162 <div class="codehilite"><pre><span></span><code><span class="o">&gt;&gt;&gt;</span> <span class="n">emoji</span> <span class="o">=</span> <span class="s2">"π"</span> |
|
|
|
163 <span class="o">&gt;&gt;&gt;</span> <span class="n">emoji</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"utf-8"</span><span class="p">)</span> |
|
|
|
164 <span class="sa">b</span><span class="s1">'</span><span class="se">\xf0\x9f\x98\x82</span><span class="s1">'</span> |
|
|
|
165 </code></pre></div> |
|
|
|
166 |
|
|
|
167 <p> |
|
|
|
168 Encoding a Unicode codepoint into bytes is a multi-step process. The first step is determining the number of octets required to encode the codepoint. The codepoint value for "Face with Tears of Joy" ( π ) is <code>0x1F602</code>. From the previous diagram the value <code>0x1F602</code> falls in the range for a 4 octets header (between <code>0x10000</code> and <code>0x10FFFF</code>). |
|
|
|
169 </p> |
|
|
|
170 |
|
|
|
171 <p> |
|
|
|
172 Next step is converting the codepoint value <code>0x1F602</code> into binary. In Python you can do <code>f"{0x1F602:b}"</code> which will return <code>'111β1101100β0000010'</code> as a string. This value is padded with zeroes until there are 21 bits to fit the layout for 4 octets. This padded value can be seen on the top of the "UTF-8 encoding" section in the diagram as "<code>000 011β111 011β000 000β010</code>". |
|
|
|
173 </p> |
|
|
|
174 |
|
|
|
175 </div> |
|
|
|
176 |
|
|
|
177 <div class="col-6"> |
|
|
|
178 |
|
|
|
179 <center> |
|
|
|
180 <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="401px" viewBox="-0.5 -0.5 401 441" style="max-width:100%;max-height:441px;"><defs/><g><rect x="0" y="0" width="400" height="140" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 7 70)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 138px; height: 1px; padding-top: 70px; margin-left: -62px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">UNICODE CODEPOINT</div></div></div></foreignObject><text x="7" y="90" fill="#333333" font-family="monospace" font-size="20px" text-anchor="middle">UNICODE CODEPO...</text></switch></g><rect x="0" y="160" width="400" height="180" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 7 250)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 178px; height: 1px; padding-top: 250px; margin-left: -82px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><div>UTF-8 ENCODING</div></div></div></div></foreignObject><text x="7" y="270" fill="#333333" font-family="monospace" font-size="20px" text-anchor="middle">UTF-8 ENCODING</text></switch></g><rect x="0" y="360" width="400" height="80" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 7 400)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 400px; margin-left: -32px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><div>BYTES</div></div></div></div></foreignObject><text x="7" y="420" fill="#333333" font-family="monospace" font-size="20px" text-anchor="middle">BYTES</text></switch></g><rect x="310" y="380" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 400px; margin-left: 311px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>82</div></div></div></foreignObject><text x="350" y="406" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0x82</text></switch></g><rect x="230" y="380" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 400px; margin-left: 231px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>98</div></div></div></foreignObject><text x="270" y="406" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0x98</text></switch></g><rect x="150" y="380" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 400px; margin-left: 151px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>9F</div></div></div></foreignObject><text x="190" y="406" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0x9F</text></switch></g><rect x="70" y="380" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 400px; margin-left: 71px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>F0</div></div></div></foreignObject><text x="110" y="406" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0xF0</text></switch></g><rect x="70" y="260" width="50" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 48px; height: 1px; padding-top: 280px; margin-left: 71px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">11110</div></div></div></foreignObject><text x="95" y="284" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">11110</text></switch></g><rect x="120" y="260" width="30" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 280px; margin-left: 121px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">000</div></div></div></foreignObject><text x="135" y="284" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">000</text></switch></g><rect x="150" y="260" width="20" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 18px; height: 1px; padding-top: 280px; margin-left: 151px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10</div></div></div></foreignObject><text x="160" y="284" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10</text></switch></g><rect x="170" y="260" width="60" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 280px; margin-left: 171px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">011β111</div></div></div></foreignObject><text x="200" y="284" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">011β111</text></switch></g><rect x="230" y="260" width="20" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 18px; height: 1px; padding-top: 280px; margin-left: 231px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10</div></div></div></foreignObject><text x="240" y="284" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10</text></switch></g><rect x="250" y="260" width="60" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 280px; margin-left: 251px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">011β000</div></div></div></foreignObject><text x="280" y="284" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">011β000</text></switch></g><rect x="70" y="180" width="320" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 318px; height: 1px; padding-top: 190px; margin-left: 71px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">000 011β111 011β000 000β010</div></div></div></foreignObject><text x="230" y="194" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">000 011β111 011β000 000β010</text></switch></g><rect x="310" y="260" width="20" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 18px; height: 1px; padding-top: 280px; margin-left: 311px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10</div></div></div></foreignObject><text x="320" y="284" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10</text></switch></g><rect x="330" y="260" width="60" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 280px; margin-left: 331px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">000β010</div></div></div></foreignObject><text x="360" y="284" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">000β010</text></switch></g><rect x="150" y="90" width="160" height="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 105px; margin-left: 151px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font style="font-size: 20px">U+1F602</font></div></div></div></foreignObject><text x="230" y="109" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">U+1F602</text></switch></g><rect x="150" y="20" width="160" height="70" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 55px; margin-left: 151px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font style="font-size: 36px">π</font></div></div></div></foreignObject><text x="230" y="59" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">π</text></switch></g><path d="M 310 120 L 390 180" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 230 120 L 230 173.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 230 178.88 L 226.5 171.88 L 230 173.63 L 233.5 171.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="70" y="200" width="80" height="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 210px; margin-left: 71px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">000</div></div></div></foreignObject><text x="110" y="214" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">000</text></switch></g><rect x="150" y="200" width="80" height="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 210px; margin-left: 151px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">011β111</div></div></div></foreignObject><text x="190" y="214" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">011β111</text></switch></g><rect x="230" y="200" width="80" height="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 210px; margin-left: 231px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">011β000</div></div></div></foreignObject><text x="270" y="214" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">011β000</text></switch></g><rect x="310" y="200" width="80" height="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 210px; margin-left: 311px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">000β010</div></div></div></foreignObject><text x="350" y="214" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">000β010</text></switch></g><path d="M 110 220 L 131.62 254.6" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 134.41 259.05 L 127.73 254.97 L 131.62 254.6 L 133.67 251.26 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 190 220 L 198.46 253.82" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 199.73 258.92 L 194.64 252.97 L 198.46 253.82 L 201.43 251.28 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 270 220 L 278.46 253.82" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 279.73 258.92 L 274.64 252.97 L 278.46 253.82 L 281.43 251.28 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 350 220 L 358.46 253.82" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 359.73 258.92 L 354.64 252.97 L 358.46 253.82 L 361.43 251.28 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="70" y="300" width="80" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 310px; margin-left: 71px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">111β10000</div></div></div></foreignObject><text x="110" y="314" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">111β10000</text></switch></g><rect x="150" y="300" width="80" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 310px; margin-left: 151px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">100β11111</div></div></div></foreignObject><text x="190" y="314" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">100β11111</text></switch></g><rect x="230" y="300" width="80" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 310px; margin-left: 231px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">100β11000</div></div></div></foreignObject><text x="270" y="314" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">100β11000</text></switch></g><rect x="310" y="300" width="80" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 310px; margin-left: 311px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">100β00010</div></div></div></foreignObject><text x="350" y="314" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">100β00010</text></switch></g><path d="M 99.5 320 L 99.5 373.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 99.5 378.88 L 96 371.88 L 99.5 373.63 L 103 371.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 179.5 320 L 179.5 373.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 179.5 378.88 L 176 371.88 L 179.5 373.63 L 183 371.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 260 320 L 260 373.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 260 378.88 L 256.5 371.88 L 260 373.63 L 263.5 371.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 339 320 L 339 373.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 339 378.88 L 335.5 371.88 L 339 373.63 L 342.5 371.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 70 260 L 70 220" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 70 320 L 70 380" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 70 180 L 150 120" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg></center> |
|
|
|
181 |
|
|
|
182 </div> |
|
|
|
183 |
|
|
|
184 <p></div></p> |
|
|
|
185 |
|
|
|
186 <p>From there we lay out our four octets, 1 header and 3 tail octets for a total of 4 octets. There are 21 empty bits to fill with data. Starting with the third tail octet from right to left we begin filling the empty bits in each octet. You can follow where each bit ends up with the arrows.</p> |
|
|
|
187 |
|
|
|
188 <p>After that we turn each 8 bit grouping into a byte which we display in hexadecimal at the bottom of the diagram. This value matches what we expected to receive from UTF-8 encoding this character: <strong>Success!</strong> β¨</p> |
|
|
|
189 |
|
|
|
190 <p>Decoding a Unicode codepoint from bytes only requires reversing the above process. Each byte will be examined first for the header type and then individual bits will be extracted from each octet and added together to reproduce the codepoint. </p> |
|
|
|
191 |
|
|
|
192 <blockquote> |
|
|
|
193 <p><strong>NOTE:</strong> You can always find a codepoint boundary from an arbitrary point in a stream of octets by moving left an octet each time the current octet starts with the bit prefix <code>10</code> which indicates a tail octet. At most you'll have to move left 3 octets to find the nearest header octet.</p> |
|
|
|
194 </blockquote> |
|
|
|
195 |
|
|
|
196 <div class="row"> |
|
|
|
197 <div class="col-6"> |
|
|
|
198 |
|
|
|
199 <h2>Why is UTF-8 everywhere?</h2> |
|
|
|
200 |
|
|
|
201 <p> |
|
|
|
202 Back when UTF-8 was first introduced there were many systems that didn't understand any character encoding beyond "<a href="https://datatracker.ietf.org/doc/html/rfc20">US-ASCII</a>". This meant whenever data encoded with another Unicode encoding was used then that system would produce garbage, even if the characters were within the US-ASCII range. |
|
|
|
203 </p> |
|
|
|
204 |
|
|
|
205 <p> |
|
|
|
206 UTF-8's use of byte prefixing <code>0</code> to be identical to the US-ASCII range in <code>0x00-0x7F</code> means that all characters within the US-ASCII range are encoded exactly as they would had they been explicitly encoded using US-ASCII instead of UTF-8. |
|
|
|
207 </p> |
|
|
|
208 |
|
|
|
209 <p> |
|
|
|
210 This was a big win for compatibility as it <strong>meant many systems could start using UTF-8 as an encoding immediately</strong>. As long as input data wasn't outside of the US-ASCII range the encoded bytes would not change which allowed for incremental adoption within a group of systems instead of having to switch "all at once" to a new encoding. |
|
|
|
211 </p> |
|
|
|
212 |
|
|
|
213 </div> |
|
|
|
214 |
|
|
|
215 <div class="col-6"> |
|
|
|
216 |
|
|
|
217 <center> |
|
|
|
218 <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="341px" viewBox="-0.5 -0.5 341 441" style="max-width:100%;max-height:441px;"><defs/><g><rect x="90" y="0" width="160" height="140" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 97 70)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 138px; height: 1px; padding-top: 70px; margin-left: 28px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">UNICODE CODEPOINT</div></div></div></foreignObject><text x="97" y="90" fill="#333333" font-family="monospace" font-size="20px" text-anchor="middle">UNICODE CODEPO...</text></switch></g><rect x="0" y="160" width="160" height="180" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 7 250)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 178px; height: 1px; padding-top: 250px; margin-left: -82px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><div>UTF-8 ENCODING</div></div></div></div></foreignObject><text x="7" y="270" fill="#333333" font-family="monospace" font-size="20px" text-anchor="middle">UTF-8 ENCODING</text></switch></g><rect x="0" y="360" width="160" height="80" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 7 400)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 400px; margin-left: -32px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><div>BYTES</div></div></div></div></foreignObject><text x="7" y="420" fill="#333333" font-family="monospace" font-size="20px" text-anchor="middle">BYTES</text></switch></g><rect x="160" y="20" width="80" height="70" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 55px; margin-left: 161px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font style="font-size: 36px">a</font></div></div></div></foreignObject><text x="200" y="59" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">a</text></switch></g><rect x="160" y="90" width="80" height="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 105px; margin-left: 161px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font style="font-size: 20px">U+57</font></div></div></div></foreignObject><text x="200" y="111" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">U+57</text></switch></g><rect x="70" y="180" width="80" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 190px; margin-left: 71px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">101β0111</div></div></div></foreignObject><text x="110" y="194" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">101β0111</text></switch></g><rect x="70" y="260" width="10" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 8px; height: 1px; padding-top: 280px; margin-left: 71px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">0</div></div></div></foreignObject><text x="75" y="284" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">0</text></switch></g><rect x="80" y="260" width="70" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 280px; margin-left: 81px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">101β0111</div></div></div></foreignObject><text x="115" y="284" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">101β0111</text></switch></g><rect x="70" y="380" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 400px; margin-left: 71px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>57</div></div></div></foreignObject><text x="110" y="406" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0x57</text></switch></g><path d="M 110 220 L 114.21 253.68" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 114.86 258.89 L 110.52 252.38 L 114.21 253.68 L 117.47 251.51 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="70" y="300" width="80" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 310px; margin-left: 71px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">010β10111</div></div></div></foreignObject><text x="110" y="314" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">010β10111</text></switch></g><path d="M 110 320 L 110 373.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 110 378.88 L 106.5 371.88 L 110 373.63 L 113.5 371.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="70" y="200" width="80" height="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 210px; margin-left: 71px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">101β0111</div></div></div></foreignObject><text x="110" y="214" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">101β0111</text></switch></g><path d="M 70 380 L 70 320" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 150 380 L 150 320" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 150 220 L 150 260" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 70 220 L 70 260" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 160 120 L 70 180" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 200 140 L 150 180" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><rect x="180" y="160" width="160" height="180" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 187 250)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 178px; height: 1px; padding-top: 250px; margin-left: 98px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">ASCII ENCODING</div></div></div></foreignObject><text x="187" y="270" fill="#333333" font-family="monospace" font-size="20px" text-anchor="middle">ASCII ENCODING</text></switch></g><rect x="250" y="180" width="80" height="140" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 250px; margin-left: 251px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">010β10111</div></div></div></foreignObject><text x="290" y="254" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">010β10111</text></switch></g><path d="M 240 120 L 330 180" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 202 140 L 250 180" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 200 120 L 284.7 176.47" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 289.07 179.38 L 281.3 178.41 L 284.7 176.47 L 285.19 172.58 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 200 120 L 115.3 176.47" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 110.93 179.38 L 114.81 172.58 L 115.3 176.47 L 118.7 178.41 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="180" y="360" width="160" height="80" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 187 400)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 400px; margin-left: 148px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><div>BYTES</div></div></div></div></foreignObject><text x="187" y="420" fill="#333333" font-family="monospace" font-size="20px" text-anchor="middle">BYTES</text></switch></g><rect x="250" y="380" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 400px; margin-left: 251px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>57</div></div></div></foreignObject><text x="290" y="406" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0x57</text></switch></g><path d="M 290 320 L 290 373.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 290 378.88 L 286.5 371.88 L 290 373.63 L 293.5 371.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 250 320 L 250 380" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 330 320 L 330 380" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg></center> |
|
|
|
219 |
|
|
|
220 </div> |
|
|
|
221 |
|
|
|
222 <p></div></p> |
|
|
|
223 |
|
|
|
224 <h2>Giant reference card</h2> |
|
|
|
225 |
|
|
|
226 <p>Below is a diagram which shows how all the different possible headers that a codepoint could be encoded to in UTF-8. You can use it for your reference or just admire all the time I spent in <a href="https://www.diagrams.net">diagrams.net</a> π
.</p> |
|
|
|
227 |
|
|
|
228 <p>Grapheme clusters are mentioned in the diagram, simply put they are multiple codepoints that when placed together will "combine" into a single "thing" drawn on the screen (that "thing" being a "<a href="https://en.wikipedia.org/wiki/Grapheme">grapheme</a>"). Maybe I'll write about these in the future!</p> |
|
|
|
229 |
|
|
|
230 <p><center> |
|
|
|
231 <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="721px" viewBox="-0.5 -0.5 721 1081" style="max-width:100%;max-height:1081px;"><defs/><g><rect x="0" y="0" width="400" height="160" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 7 80)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 80px; margin-left: -72px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">GRAPHEME CLUSTER</div></div></div></foreignObject><text x="7" y="100" fill="#333333" font-family="monospace" font-size="20px" text-anchor="middle">GRAPHEME CLUSTER</text></switch></g><rect x="0" y="180" width="400" height="140" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 7 250)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 138px; height: 1px; padding-top: 250px; margin-left: -62px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">UNICODE CODEPOINT</div></div></div></foreignObject><text x="7" y="270" fill="#333333" font-family="monospace" font-size="20px" text-anchor="middle">UNICODE CODEPO...</text></switch></g><rect x="0" y="340" width="720" height="180" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 7 430)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 178px; height: 1px; padding-top: 430px; margin-left: -82px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><div>UTF-8 ENCODING</div></div></div></div></foreignObject><text x="7" y="450" fill="#333333" font-family="monospace" font-size="20px" text-anchor="middle">UTF-8 ENCODING</text></switch></g><rect x="0" y="540" width="720" height="80" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 7 580)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 580px; margin-left: -32px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><div>BYTES</div></div></div></div></foreignObject><text x="7" y="600" fill="#333333" font-family="monospace" font-size="20px" text-anchor="middle">BYTES</text></switch></g><rect x="0" y="640" width="720" height="140" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 7 710)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 138px; height: 1px; padding-top: 710px; margin-left: -62px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">UNICODE CODEPOINT</div></div></div></foreignObject><text x="7" y="730" fill="#333333" font-family="monospace" font-size="20px" text-anchor="middle">UNICODE CODEPO...</text></switch></g><rect x="0" y="800" width="720" height="180" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 7 890)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 178px; height: 1px; padding-top: 890px; margin-left: -82px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><div>UTF-8 ENCODING</div></div></div></div></foreignObject><text x="7" y="910" fill="#333333" font-family="monospace" font-size="20px" text-anchor="middle">UTF-8 ENCODING</text></switch></g><rect x="0" y="1000" width="720" height="80" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 7 1040)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 1040px; margin-left: -32px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><div>BYTES</div></div></div></div></foreignObject><text x="7" y="1060" fill="#333333" font-family="monospace" font-size="20px" text-anchor="middle">BYTES</text></switch></g><rect x="110" y="660" width="80" height="70" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 695px; margin-left: 111px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font style="font-size: 36px">a</font></div></div></div></foreignObject><text x="150" y="699" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">a</text></switch></g><path d="M 150 760 L 150 813.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 150 818.88 L 146.5 811.88 L 150 813.63 L 153.5 811.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="110" y="730" width="80" height="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 745px; margin-left: 111px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font style="font-size: 20px">U+57</font></div></div></div></foreignObject><text x="150" y="751" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">U+57</text></switch></g><rect x="110" y="820" width="80" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 830px; margin-left: 111px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">1010111</div></div></div></foreignObject><text x="150" y="834" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">1010111</text></switch></g><rect x="110" y="900" width="10" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 8px; height: 1px; padding-top: 920px; margin-left: 111px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">0</div></div></div></foreignObject><text x="115" y="924" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">0</text></switch></g><rect x="120" y="900" width="70" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 920px; margin-left: 121px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">1010111</div></div></div></foreignObject><text x="155" y="924" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">1010111</text></switch></g><rect x="110" y="1020" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 1040px; margin-left: 111px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>57</div></div></div></foreignObject><text x="150" y="1046" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0x57</text></switch></g><path d="M 150 860 L 154.21 893.68" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 154.86 898.89 L 150.52 892.38 L 154.21 893.68 L 157.47 891.51 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="110" y="940" width="80" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 950px; margin-left: 111px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">01010111</div></div></div></foreignObject><text x="150" y="954" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">01010111</text></switch></g><path d="M 150 960 L 150 1013.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 150 1018.88 L 146.5 1011.88 L 150 1013.63 L 153.5 1011.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="110" y="840" width="80" height="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 850px; margin-left: 111px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">1010111</div></div></div></foreignObject><text x="150" y="854" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">1010111</text></switch></g><path d="M 110 1020 L 110 960" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 190 1020 L 190 960" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 190 860 L 190 900" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 110 860 L 110 900" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 110 760 L 110 820" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 190 760 L 190 820" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><rect x="430" y="660" width="240" height="70" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 238px; height: 1px; padding-top: 695px; margin-left: 431px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 36px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">α»</div></div></div></foreignObject><text x="550" y="706" fill="rgb(0, 0, 0)" font-family="monospace" font-size="36px" text-anchor="middle">α»</text></switch></g><path d="M 550 760 L 550 813.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 550 818.88 L 546.5 811.88 L 550 813.63 L 553.5 811.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="430" y="730" width="240" height="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 238px; height: 1px; padding-top: 745px; margin-left: 431px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font style="font-size: 20px">U+1EDF</font></div></div></div></foreignObject><text x="550" y="751" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">U+1EDF</text></switch></g><rect x="430" y="820" width="240" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 238px; height: 1px; padding-top: 830px; margin-left: 431px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">0001 111011 011111</div></div></div></foreignObject><text x="550" y="834" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">0001 111011 011111</text></switch></g><rect x="430" y="900" width="40" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 38px; height: 1px; padding-top: 920px; margin-left: 431px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">1110</div></div></div></foreignObject><text x="450" y="924" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">1110</text></switch></g><rect x="470" y="900" width="40" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 38px; height: 1px; padding-top: 920px; margin-left: 471px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">0001</div></div></div></foreignObject><text x="490" y="924" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">0001</text></switch></g><rect x="430" y="1020" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 1040px; margin-left: 431px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>E1</div></div></div></foreignObject><text x="470" y="1046" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0xE1</text></switch></g><rect x="510" y="1020" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 1040px; margin-left: 511px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>BB</div></div></div></foreignObject><text x="550" y="1046" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0xBB</text></switch></g><rect x="510" y="900" width="20" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 18px; height: 1px; padding-top: 920px; margin-left: 511px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10</div></div></div></foreignObject><text x="520" y="924" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10</text></switch></g><rect x="530" y="900" width="60" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 920px; margin-left: 531px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">111011</div></div></div></foreignObject><text x="560" y="924" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">111011</text></switch></g><rect x="590" y="900" width="20" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 18px; height: 1px; padding-top: 920px; margin-left: 591px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10</div></div></div></foreignObject><text x="600" y="924" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10</text></switch></g><rect x="610" y="900" width="60" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 920px; margin-left: 611px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">011111</div></div></div></foreignObject><text x="640" y="924" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">011111</text></switch></g><rect x="590" y="1020" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 1040px; margin-left: 591px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>9F</div></div></div></foreignObject><text x="630" y="1046" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0x9F</text></switch></g><rect x="230" y="660" width="160" height="70" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 695px; margin-left: 231px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font style="font-size: 36px">Δ</font></div></div></div></foreignObject><text x="310" y="699" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">Δ</text></switch></g><path d="M 310 760 L 310 813.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 310 818.88 L 306.5 811.88 L 310 813.63 L 313.5 811.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="230" y="730" width="160" height="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 745px; margin-left: 231px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font style="font-size: 20px">U+0111</font></div></div></div></foreignObject><text x="310" y="751" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">U+0111</text></switch></g><rect x="230" y="820" width="160" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 830px; margin-left: 231px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">00100 010001</div></div></div></foreignObject><text x="310" y="834" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">00100 010001</text></switch></g><rect x="230" y="900" width="30" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 920px; margin-left: 231px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">110</div></div></div></foreignObject><text x="245" y="924" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">110</text></switch></g><rect x="260" y="900" width="50" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 48px; height: 1px; padding-top: 920px; margin-left: 261px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">00100</div></div></div></foreignObject><text x="285" y="924" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">00100</text></switch></g><rect x="230" y="1020" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 1040px; margin-left: 231px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>C4</div></div></div></foreignObject><text x="270" y="1046" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0xC4</text></switch></g><rect x="310" y="1020" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 1040px; margin-left: 311px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>91</div></div></div></foreignObject><text x="350" y="1046" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0x91</text></switch></g><rect x="310" y="900" width="20" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 18px; height: 1px; padding-top: 920px; margin-left: 311px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10</div></div></div></foreignObject><text x="320" y="924" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10</text></switch></g><rect x="330" y="900" width="60" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 920px; margin-left: 331px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">010001</div></div></div></foreignObject><text x="360" y="924" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">010001</text></switch></g><rect x="230" y="840" width="80" height="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 850px; margin-left: 231px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">00100</div></div></div></foreignObject><text x="270" y="854" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">00100</text></switch></g><rect x="310" y="840" width="80" height="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 850px; margin-left: 311px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">010001</div></div></div></foreignObject><text x="350" y="854" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">010001</text></switch></g><rect x="430" y="840" width="80" height="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 850px; margin-left: 431px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">0001</div></div></div></foreignObject><text x="470" y="854" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">0001</text></switch></g><rect x="510" y="840" width="80" height="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 850px; margin-left: 511px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">111011</div></div></div></foreignObject><text x="550" y="854" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">111011</text></switch></g><rect x="590" y="840" width="80" height="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 850px; margin-left: 591px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">011111</div></div></div></foreignObject><text x="630" y="854" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">011111</text></switch></g><path d="M 270 860 L 282.76 894.04" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 284.61 898.95 L 278.87 893.63 L 282.76 894.04 L 285.43 891.17 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 350 860 L 358.46 893.82" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 359.73 898.92 L 354.64 892.97 L 358.46 893.82 L 361.43 891.28 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="230" y="940" width="80" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 950px; margin-left: 231px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">11000100</div></div></div></foreignObject><text x="270" y="954" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">11000100</text></switch></g><rect x="310" y="940" width="80" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 950px; margin-left: 311px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10010001</div></div></div></foreignObject><text x="350" y="954" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10010001</text></switch></g><rect x="430" y="940" width="80" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 950px; margin-left: 431px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">11100001</div></div></div></foreignObject><text x="470" y="954" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">11100001</text></switch></g><rect x="510" y="940" width="80" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 950px; margin-left: 511px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10111011</div></div></div></foreignObject><text x="550" y="954" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10111011</text></switch></g><rect x="590" y="940" width="80" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 950px; margin-left: 591px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10011111</div></div></div></foreignObject><text x="630" y="954" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10011111</text></switch></g><path d="M 264 960 L 264 1013.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 264 1018.88 L 260.5 1011.88 L 264 1013.63 L 267.5 1011.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 344 960 L 344 1013.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 344 1018.88 L 340.5 1011.88 L 344 1013.63 L 347.5 1011.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 473 960 L 473 1013.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 473 1018.88 L 469.5 1011.88 L 473 1013.63 L 476.5 1011.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 553.5 960 L 553.5 1013.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 553.5 1018.88 L 550 1011.88 L 553.5 1013.63 L 557 1011.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 633.5 960 L 633.5 1013.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 633.5 1018.88 L 630 1011.88 L 633.5 1013.63 L 637 1011.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 470 860 L 487.15 894.3" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 489.5 899 L 483.24 894.3 L 487.15 894.3 L 489.5 891.17 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 550 860 L 558.46 893.82" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 559.73 898.92 L 554.64 892.97 L 558.46 893.82 L 561.43 891.28 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 630 860 L 638.46 893.82" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 639.73 898.92 L 634.64 892.97 L 638.46 893.82 L 641.43 891.28 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="310" y="560" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 580px; margin-left: 311px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>BA</div></div></div></foreignObject><text x="350" y="586" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0xBA</text></switch></g><rect x="230" y="560" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 580px; margin-left: 231px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>87</div></div></div></foreignObject><text x="270" y="586" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0x87</text></switch></g><rect x="150" y="560" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 580px; margin-left: 151px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>9F</div></div></div></foreignObject><text x="190" y="586" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0x9F</text></switch></g><rect x="70" y="560" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 580px; margin-left: 71px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>F0</div></div></div></foreignObject><text x="110" y="586" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0xF0</text></switch></g><rect x="70" y="440" width="50" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 48px; height: 1px; padding-top: 460px; margin-left: 71px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">11110</div></div></div></foreignObject><text x="95" y="464" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">11110</text></switch></g><rect x="120" y="440" width="30" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 460px; margin-left: 121px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">000</div></div></div></foreignObject><text x="135" y="464" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">000</text></switch></g><rect x="150" y="440" width="20" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 18px; height: 1px; padding-top: 460px; margin-left: 151px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10</div></div></div></foreignObject><text x="160" y="464" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10</text></switch></g><rect x="170" y="440" width="60" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 460px; margin-left: 171px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">011111</div></div></div></foreignObject><text x="200" y="464" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">011111</text></switch></g><rect x="230" y="440" width="20" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 18px; height: 1px; padding-top: 460px; margin-left: 231px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10</div></div></div></foreignObject><text x="240" y="464" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10</text></switch></g><rect x="250" y="440" width="60" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 460px; margin-left: 251px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">000111</div></div></div></foreignObject><text x="280" y="464" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">000111</text></switch></g><rect x="70" y="360" width="320" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 318px; height: 1px; padding-top: 370px; margin-left: 71px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">000 011111 000111 111010</div></div></div></foreignObject><text x="230" y="374" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">000 011111 000111 111010</text></switch></g><rect x="310" y="440" width="20" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 18px; height: 1px; padding-top: 460px; margin-left: 311px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10</div></div></div></foreignObject><text x="320" y="464" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10</text></switch></g><rect x="330" y="440" width="60" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 460px; margin-left: 331px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">111010</div></div></div></foreignObject><text x="360" y="464" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">111010</text></switch></g><rect x="70" y="270" width="160" height="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 285px; margin-left: 71px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font style="font-size: 20px">U+1F1FA</font></div></div></div></foreignObject><text x="150" y="289" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">U+1F1FA</text></switch></g><path d="M 310 270 L 310 250 L 310 290 L 310 276.37" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 310 271.12 L 313.5 278.12 L 310 276.37 L 306.5 278.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="230" y="270" width="160" height="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 285px; margin-left: 231px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font style="font-size: 20px">U+1F1F8</font></div></div></div></foreignObject><text x="310" y="289" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">U+1F1F8</text></switch></g><rect x="70" y="200" width="160" height="70" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 235px; margin-left: 71px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font style="font-size: 36px">πΊ</font></div></div></div></foreignObject><text x="150" y="239" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">πΊ</text></switch></g><rect x="230" y="200" width="160" height="70" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 235px; margin-left: 231px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font style="font-size: 36px">πΈ</font></div></div></div></foreignObject><text x="310" y="239" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">πΈ</text></switch></g><rect x="70" y="20" width="320" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 318px; height: 1px; padding-top: 60px; margin-left: 71px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font style="font-size: 48px">πΊπΈ</font></div></div></div></foreignObject><text x="230" y="64" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">πΊπΈ</text></switch></g><rect x="630" y="560" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 580px; margin-left: 631px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>B8</div></div></div></foreignObject><text x="670" y="586" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0xB8</text></switch></g><rect x="550" y="560" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 580px; margin-left: 551px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>87</div></div></div></foreignObject><text x="590" y="586" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0x87</text></switch></g><rect x="470" y="560" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 580px; margin-left: 471px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>9F</div></div></div></foreignObject><text x="510" y="586" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0x9F</text></switch></g><rect x="390" y="560" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 580px; margin-left: 391px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font color="#808080">0x</font>F0</div></div></div></foreignObject><text x="430" y="586" fill="rgb(0, 0, 0)" font-family="monospace" font-size="20px" text-anchor="middle">0xF0</text></switch></g><rect x="390" y="440" width="50" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 48px; height: 1px; padding-top: 460px; margin-left: 391px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">11110</div></div></div></foreignObject><text x="415" y="464" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">11110</text></switch></g><rect x="440" y="440" width="30" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 460px; margin-left: 441px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">000</div></div></div></foreignObject><text x="455" y="464" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">000</text></switch></g><rect x="470" y="440" width="20" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 18px; height: 1px; padding-top: 460px; margin-left: 471px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10</div></div></div></foreignObject><text x="480" y="464" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10</text></switch></g><rect x="490" y="440" width="60" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 460px; margin-left: 491px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">011111</div></div></div></foreignObject><text x="520" y="464" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">011111</text></switch></g><rect x="550" y="440" width="20" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 18px; height: 1px; padding-top: 460px; margin-left: 551px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10</div></div></div></foreignObject><text x="560" y="464" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10</text></switch></g><rect x="570" y="440" width="60" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 460px; margin-left: 571px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">000111</div></div></div></foreignObject><text x="600" y="464" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">000111</text></switch></g><rect x="630" y="440" width="20" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 18px; height: 1px; padding-top: 460px; margin-left: 631px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10</div></div></div></foreignObject><text x="640" y="464" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10</text></switch></g><rect x="650" y="440" width="60" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 460px; margin-left: 651px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">111000</div></div></div></foreignObject><text x="680" y="464" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">111000</text></switch></g><rect x="390" y="360" width="320" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 318px; height: 1px; padding-top: 370px; margin-left: 391px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">000 011111 000111 111000</div></div></div></foreignObject><text x="550" y="374" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">000 011111 000111 111000</text></switch></g><path d="M 70 140 L 70 200" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 230 300 L 390 360" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 390 300 L 710 360" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 390 360 L 390 600" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 390 140 L 390 200" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 230 140 L 230 200" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 150 100 L 150 193.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 150 198.88 L 146.5 191.88 L 150 193.63 L 153.5 191.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 310 100 L 310 193.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 310 198.88 L 306.5 191.88 L 310 193.63 L 313.5 191.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 310 300 L 543.82 358.46" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 548.92 359.73 L 541.28 361.43 L 543.82 358.46 L 542.97 354.64 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 150 300 L 224.91 356.18" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 229.11 359.33 L 221.41 357.93 L 224.91 356.18 L 225.61 352.33 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="70" y="100" width="160" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 120px; margin-left: 71px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 22px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font style="font-size: 22px">πΊ</font></div></div></div></foreignObject><text x="150" y="127" fill="rgb(0, 0, 0)" font-family="monospace" font-size="22px" text-anchor="middle">πΊ</text></switch></g><rect x="230" y="100" width="160" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 120px; margin-left: 231px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 22px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><font style="font-size: 22px">πΈ</font></div></div></div></foreignObject><text x="310" y="127" fill="rgb(0, 0, 0)" font-family="monospace" font-size="22px" text-anchor="middle">πΈ</text></switch></g><rect x="70" y="380" width="80" height="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 390px; margin-left: 71px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">000</div></div></div></foreignObject><text x="110" y="394" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">000</text></switch></g><rect x="150" y="380" width="80" height="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 390px; margin-left: 151px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">011111</div></div></div></foreignObject><text x="190" y="394" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">011111</text></switch></g><rect x="230" y="380" width="80" height="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 390px; margin-left: 231px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">000111</div></div></div></foreignObject><text x="270" y="394" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">000111</text></switch></g><rect x="310" y="380" width="80" height="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 390px; margin-left: 311px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">111010</div></div></div></foreignObject><text x="350" y="394" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">111010</text></switch></g><rect x="390" y="380" width="80" height="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 390px; margin-left: 391px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">000</div></div></div></foreignObject><text x="430" y="394" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">000</text></switch></g><rect x="470" y="380" width="80" height="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 390px; margin-left: 471px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">011111</div></div></div></foreignObject><text x="510" y="394" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">011111</text></switch></g><rect x="550" y="380" width="80" height="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 390px; margin-left: 551px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">000111</div></div></div></foreignObject><text x="590" y="394" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">000111</text></switch></g><rect x="630" y="380" width="80" height="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 390px; margin-left: 631px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">111000</div></div></div></foreignObject><text x="670" y="394" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">111000</text></switch></g><path d="M 110 400 L 131.62 434.6" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 134.41 439.05 L 127.73 434.97 L 131.62 434.6 L 133.67 431.26 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 430 400 L 451.62 434.6" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 454.41 439.05 L 447.73 434.97 L 451.62 434.6 L 453.67 431.26 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 190 400 L 198.46 433.82" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 199.73 438.92 L 194.64 432.97 L 198.46 433.82 L 201.43 431.28 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 270 400 L 278.46 433.82" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 279.73 438.92 L 274.64 432.97 L 278.46 433.82 L 281.43 431.28 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 350 400 L 358.46 433.82" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 359.73 438.92 L 354.64 432.97 L 358.46 433.82 L 361.43 431.28 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 510 400 L 518.46 433.82" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 519.73 438.92 L 514.64 432.97 L 518.46 433.82 L 521.43 431.28 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 590 400 L 598.46 433.82" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 599.73 438.92 L 594.64 432.97 L 598.46 433.82 L 601.43 431.28 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 670 400 L 678.46 433.82" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 679.73 438.92 L 674.64 432.97 L 678.46 433.82 L 681.43 431.28 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="70" y="480" width="80" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 490px; margin-left: 71px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">11110000</div></div></div></foreignObject><text x="110" y="494" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">11110000</text></switch></g><rect x="150" y="480" width="80" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 490px; margin-left: 151px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10011111</div></div></div></foreignObject><text x="190" y="494" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10011111</text></switch></g><rect x="230" y="480" width="80" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 490px; margin-left: 231px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10000111</div></div></div></foreignObject><text x="270" y="494" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10000111</text></switch></g><rect x="310" y="480" width="80" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 490px; margin-left: 311px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10111010</div></div></div></foreignObject><text x="350" y="494" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10111010</text></switch></g><rect x="390" y="480" width="80" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 490px; margin-left: 391px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">11110000</div></div></div></foreignObject><text x="430" y="494" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">11110000</text></switch></g><rect x="470" y="480" width="80" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 490px; margin-left: 471px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10011111</div></div></div></foreignObject><text x="510" y="494" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10011111</text></switch></g><rect x="550" y="480" width="80" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 490px; margin-left: 551px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10000111</div></div></div></foreignObject><text x="590" y="494" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10000111</text></switch></g><rect x="630" y="480" width="80" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 490px; margin-left: 631px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10111000</div></div></div></foreignObject><text x="670" y="494" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10111000</text></switch></g><path d="M 99.5 500 L 99.5 553.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 99.5 558.88 L 96 551.88 L 99.5 553.63 L 103 551.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 179.5 500 L 179.5 553.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 179.5 558.88 L 176 551.88 L 179.5 553.63 L 183 551.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 260 500 L 260 553.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 260 558.88 L 256.5 551.88 L 260 553.63 L 263.5 551.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 339 500 L 339 553.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 339 558.88 L 335.5 551.88 L 339 553.63 L 342.5 551.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 420 500 L 420 553.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 420 558.88 L 416.5 551.88 L 420 553.63 L 423.5 551.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 499 500 L 499 553.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 499 558.88 L 495.5 551.88 L 499 553.63 L 502.5 551.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 579.5 500 L 579.5 553.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 579.5 558.88 L 576 551.88 L 579.5 553.63 L 583 551.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 659.5 500 L 659.5 553.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 659.5 558.88 L 656 551.88 L 659.5 553.63 L 663 551.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 710 400 L 710 440" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 70 440 L 70 400" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 70 500 L 70 560" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 710 500 L 710 560" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 70 360 L 70 300" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><rect x="420" y="0" width="300" height="300" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 427 150)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 298px; height: 1px; padding-top: 150px; margin-left: 278px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: monospace; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">UTF-8 OCTETS</div></div></div></foreignObject><text x="427" y="170" fill="#333333" font-family="monospace" font-size="20px" text-anchor="middle">UTF-8 OCTETS</text></switch></g><rect x="470" y="20" width="10" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 8px; height: 1px; padding-top: 40px; margin-left: 471px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">0</div></div></div></foreignObject><text x="475" y="44" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">0</text></switch></g><rect x="470" y="70" width="30" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 90px; margin-left: 471px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">110</div></div></div></foreignObject><text x="485" y="94" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">110</text></switch></g><rect x="470" y="120" width="40" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 38px; height: 1px; padding-top: 140px; margin-left: 471px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">1110</div></div></div></foreignObject><text x="490" y="144" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">1110</text></switch></g><rect x="470" y="170" width="50" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 48px; height: 1px; padding-top: 190px; margin-left: 471px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">11110</div></div></div></foreignObject><text x="495" y="194" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">11110</text></switch></g><rect x="480" y="20" width="70" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 40px; margin-left: 481px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">xxxxxxx</div></div></div></foreignObject><text x="515" y="44" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">xxxxxxx</text></switch></g><rect x="500" y="70" width="50" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 48px; height: 1px; padding-top: 90px; margin-left: 501px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">xxxxx</div></div></div></foreignObject><text x="525" y="94" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">xxxxx</text></switch></g><rect x="510" y="120" width="40" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 38px; height: 1px; padding-top: 140px; margin-left: 511px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">xxxx</div></div></div></foreignObject><text x="530" y="144" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">xxxx</text></switch></g><rect x="520" y="170" width="30" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 190px; margin-left: 521px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">xxx</div></div></div></foreignObject><text x="535" y="194" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">xxx</text></switch></g><rect x="470" y="240" width="20" height="40" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 18px; height: 1px; padding-top: 260px; margin-left: 471px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10</div></div></div></foreignObject><text x="480" y="264" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">10</text></switch></g><rect x="490" y="240" width="60" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 260px; margin-left: 491px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">xxxxxx</div></div></div></foreignObject><text x="520" y="264" fill="rgb(0, 0, 0)" font-family="monospace" font-size="12px" text-anchor="middle">xxxxxx</text></switch></g><rect x="560" y="20" width="160" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 158px; height: 1px; padding-top: 40px; margin-left: 562px;"><div style="box-sizing: border-box; font-size: 0px; text-align: left;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 16px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><div>U+0000βU+007F<br />1 octet header<br /></div></div></div></div></foreignObject><text x="562" y="45" fill="rgb(0, 0, 0)" font-family="monospace" font-size="16px">U+0000βU+007F...</text></switch></g><rect x="560" y="70" width="160" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 158px; height: 1px; padding-top: 90px; margin-left: 562px;"><div style="box-sizing: border-box; font-size: 0px; text-align: left;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 16px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">U+0080βU+07FF<br />2 octets header</div></div></div></foreignObject><text x="562" y="95" fill="rgb(0, 0, 0)" font-family="monospace" font-size="16px">U+0080βU+07FF...</text></switch></g><rect x="560" y="120" width="160" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 158px; height: 1px; padding-top: 140px; margin-left: 562px;"><div style="box-sizing: border-box; font-size: 0px; text-align: left;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 16px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">U+0800βU+FFFF<br />3 octets header</div></div></div></foreignObject><text x="562" y="145" fill="rgb(0, 0, 0)" font-family="monospace" font-size="16px">U+0800βU+FFFF...</text></switch></g><rect x="560" y="170" width="160" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 158px; height: 1px; padding-top: 190px; margin-left: 562px;"><div style="box-sizing: border-box; font-size: 0px; text-align: left;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 16px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">U+10000βU+10FFFF<br />4 octets header</div></div></div></foreignObject><text x="562" y="195" fill="rgb(0, 0, 0)" font-family="monospace" font-size="16px">U+10000βU+10FFFF...</text></switch></g><rect x="560" y="240" width="160" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 158px; height: 1px; padding-top: 260px; margin-left: 562px;"><div style="box-sizing: border-box; font-size: 0px; text-align: left;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 16px; font-family: monospace; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Tail/data octet</div></div></div></foreignObject><text x="562" y="265" fill="rgb(0, 0, 0)" font-family="monospace" font-size="16px">Tail/data octet</text></switch></g><path d="M 230 760 L 230 820" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 389 760 L 389 820" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 430 760 L 430 820" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 670 760 L 669 820" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 230 860 L 230 900" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 230 960 L 230 1020" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 390 860 L 390 900" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 390 960 L 390 1020" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 430 860 L 430 900" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 430 960 L 430 1020" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 670 860 L 670 900" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 670 960 L 670 1020" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> |
|
|
|
232 </center></p> |
|
|
|
233 |
|
|
|
234 </div> |
|
|
|
235 </div> |
|
|
|
236 <div class="row"> |
|
|
|
237 <div class="col-12"> |
|
|
|
238 <center> |
|
|
|
239 <div class="how-to-subscribe"> |
|
|
|
240 Enjoy this post? <span class="heart">β€&#xFE0E</span> Subscribe for more via <a href="https://tinyletter.com/sethmlarson">the newsletter</a> or <a href="/feed">RSS</a> |
|
|
|
241 </div> |
|
|
|
242 </center> |
|
|
|
243 </div> |
|
|
|
244 </div> |
|
|
|
245 |
|
|
|
246 <div class="row"> |
|
|
|
247 <div class="col-2"></div> |
|
|
|
248 <div class="col-8"><center><small>Built with <a href="https://simplegrid.io" target="_blank" rel="nofollow noopener noreferrer">SimpleGrid</a>, <a href="https://simplegrid.io/" target="_blank" rel="nofollow noopener noreferrer">FontAwesome</a>, <a href="https://flask.palletsprojects.com" target="_blank" rel="nofollow noopener noreferrer">Flask</a>, and <a href="https://github.com/sethmlarson/sethmlarson.dev" target="_blank" rel="nofollow noopener noreferrer">more</a>.</small></center></div> |
|
|
|
249 <div class="col-2"></div> |
|
|
|
250 </div> |
|
|
|
251 </div> |
|
|
|
252 |
|
|
|
253 <!-- Google Analytics --> |
|
|
|
254 <script async src="https://www.googletagmanager.com/gtag/js?id=G-C3VD7T243W"></script> |
|
|
|
255 <script> |
|
|
|
256 window.dataLayer = window.dataLayer || []; |
|
|
|
257 function gtag(){dataLayer.push(arguments);} |
|
|
|
258 gtag('js', new Date()); |
|
|
|
259 gtag('config', 'G-C3VD7T243W'); |
|
|
|
260 </script> |
|
|
|
261 </body> |
|
|
|
262 </html></content> |
|
|
|
263 </entry> |
|
|
|
264 <entry xml:base="http://sethmlarson.dev/feed"> |
|
|
|
265 <title type="text">Strict Python function parameters</title> |
|
|
|
266 <id>http://sethmlarson.dev/blog/strict-python-function-parameters?date=2022-01-23</id> |
|
|
|
267 <updated>2022-01-23T00:00:00Z</updated> |
|
|
|
268 <published>2022-01-23T00:00:00Z</published> |
|
|
|
269 <link href="http://sethmlarson.dev/blog/strict-python-function-parameters?date=2022-01-23" /> |
|
|
|
270 <author> |
|
|
|
271 <name>Seth Michael Larson</name> |
|
|
|
272 </author> |
|
|
|
273 <content type="html"><!DOCTYPE html> |
|
|
|
274 <html lang="en"> |
|
|
|
275 <head> |
|
|
|
276 <meta charset="utf-8"> |
|
|
|
277 <title>Strict Python function parameters</title> |
|
|
|
278 <meta name="description" content="Blogging about Python and the Internet"> |
|
|
|
279 <meta name="keywords" content="blog python open source http networking security"> |
|
|
|
280 <meta name="author" content="Seth Michael Larson"> |
|
|
|
281 <meta name="viewport" content="width=device-width, initial-scale=1"> |
|
|
|
282 <meta name="format-detection" content="telephone=no"/> |
|
|
|
283 <link rel="alternate" type="application/rss+xml" title="RSS Feed" href="/feed"/> |
|
|
|
284 <link rel="icon" href="/static/favicon.ico"> |
|
|
|
285 <link rel="stylesheet" href="/static/style.css"> |
|
|
|
286 |
|
|
|
287 <meta property="og:site_name" content="Seth Michael Larson"/> |
|
|
|
288 <meta property="og:author" content="Seth Michael Larson"/> |
|
|
|
289 <meta property="og:type" content="article"/> |
|
|
|
290 <meta property="og:title" content="Strict Python function parameters"/> |
|
|
|
291 <meta property="og:description" content="What do you think about when writing a new function in Python? The function name, parameter names, optional/required parameters, and default arguments are all on the list. Here is a simple Python f..."/> |
|
|
|
292 <meta property="og:image" content="http://sethmlarson.dev/static/avatar.jpeg"/> |
|
|
|
293 <meta name="twitter:card" content="summary"/> |
|
|
|
294 <meta name="twitter:site" content="@sethmlarson"/> |
|
|
|
295 <meta name="twitter:creator" content="@sethmlarson"/> |
|
|
|
296 <meta name="twitter:title" content="Strict Python function parameters"/> |
|
|
|
297 <meta name="twitter:description" content="What do you think about when writing a new function in Python? The function name, parameter names, optional/required parameters, and default arguments are all on the list. Here is a simple Python f..."/> |
|
|
|
298 <meta property="og:image" content="http://sethmlarson.dev/static/avatar.jpeg"/> |
|
|
|
299 |
|
|
|
300 </head> |
|
|
|
301 <body> |
|
|
|
302 <div class="container"> |
|
|
|
303 <div class="row"> |
|
|
|
304 <div class="col-6"> |
|
|
|
305 <center> |
|
|
|
306 <h1 style="margin-bottom: 0.1em; font-size: 1.8em;">Seth Michael Larson</h1> |
|
|
|
307 <span style="font-style: italic;">Blogging about Python and the Internet</span> |
|
|
|
308 </center> |
|
|
|
309 </div> |
|
|
|
310 <div class="col-6"> |
|
|
|
311 <div class="navbar-outer"> |
|
|
|
312 <div class="navbar-inner"> |
|
|
|
313 <a class="icon" href="/about"> |
|
|
|
314 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"> |
|
|
|
315 <title>About</title><path d="M528 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h480c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-352 96c35.3 0 64 28.7 64 64s-28.7 64-64 64-64-28.7-64-64 28.7-64 64-64zm112 236.8c0 10.6-10 19.2-22.4 19.2H86.4C74 384 64 375.4 64 364.8v-19.2c0-31.8 30.1-57.6 67.2-57.6h5c12.3 5.1 25.7 8 39.8 8s27.6-2.9 39.8-8h5c37.1 0 67.2 25.8 67.2 57.6v19.2zM512 312c0 4.4-3.6 8-8 8H360c-4.4 0-8-3.6-8-8v-16c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16zm0-64c0 4.4-3.6 8-8 8H360c-4.4 0-8-3.6-8-8v-16c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16zm0-64c0 4.4-3.6 8-8 8H360c-4.4 0-8-3.6-8-8v-16c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16z"/> |
|
|
|
316 </svg> |
|
|
|
317 </a> |
|
|
|
318 <a class="icon" href="/blog"> |
|
|
|
319 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> |
|
|
|
320 <title>Blog</title><path d="M172.2 226.8c-14.6-2.9-28.2 8.9-28.2 23.8V301c0 10.2 7.1 18.4 16.7 22 18.2 6.8 31.3 24.4 31.3 45 0 26.5-21.5 48-48 48s-48-21.5-48-48V120c0-13.3-10.7-24-24-24H24c-13.3 0-24 10.7-24 24v248c0 89.5 82.1 160.2 175 140.7 54.4-11.4 98.3-55.4 109.7-109.7 17.4-82.9-37-157.2-112.5-172.2zM209 0c-9.2-.5-17 6.8-17 16v31.6c0 8.5 6.6 15.5 15 15.9 129.4 7 233.4 112 240.9 241.5.5 8.4 7.5 15 15.9 15h32.1c9.2 0 16.5-7.8 16-17C503.4 139.8 372.2 8.6 209 0zm.3 96c-9.3-.7-17.3 6.7-17.3 16.1v32.1c0 8.4 6.5 15.3 14.8 15.9 76.8 6.3 138 68.2 144.9 145.2.8 8.3 7.6 14.7 15.9 14.7h32.2c9.3 0 16.8-8 16.1-17.3-8.4-110.1-96.5-198.2-206.6-206.7z"/> |
|
|
|
321 </svg> |
|
|
|
322 </a> |
|
|
|
323 <a class="icon" href="https://twitter.com/sethmlarson" target="_blank" rel="nofollow noopener noreferrer"> |
|
|
|
324 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> |
|
|
|
325 <title>Twitter</title><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/> |
|
|
|
326 </svg> |
|
|
|
327 </a> |
|
|
|
328 <a class="icon" href="https://github.com/sethmlarson" target="_blank" rel="nofollow noopener noreferrer"> |
|
|
|
329 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"> |
|
|
|
330 <title>GitHub</title><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/> |
|
|
|
331 </svg> |
|
|
|
332 </a> |
|
|
|
333 <a class="icon" href="https://linkedin.com/in/sethmlarson" target="_blank" rel="nofollow noopener noreferrer"> |
|
|
|
334 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"> |
|
|
|
335 <title>LinkedIn</title><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3zM135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5zm282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9V416z"/> |
|
|
|
336 </svg> |
|
|
|
337 </a> |
|
|
|
338 </div> |
|
|
|
339 </div> |
|
|
|
340 </div> |
|
|
|
341 </div> |
|
|
|
342 |
|
|
|
343 <div class="row"> |
|
|
|
344 <div class="col-12"> |
|
|
|
345 <h2 class="blog-title" style="text-align: center">Strict Python function parameters</h2> |
|
|
|
346 <p><center>Published 2022-01-23 β <span class="heart">β€&#xFE0E</span> Subscribe for more via <a href="https://tinyletter.com/sethmlarson">the newsletter</a> or <a href="/feed">RSS</a></center></p> |
|
|
|
347 </div> |
|
|
|
348 </div> |
|
|
|
349 <div class="row"> |
|
|
|
350 <div class="col-12"> |
|
|
|
351 <p><strong>What do you think about when writing a new function in Python?</strong> The function name, parameter names, optional/required parameters, and default arguments are all on the list. Here is a simple Python function that has all these covered:</p> |
|
|
|
352 |
|
|
|
353 <div class="codehilite"><pre><span></span><code><span class="k">def</span> <span class="nf">process_data</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s2">&quot;ascii&quot;</span><span class="p">):</span> |
|
|
|
354 <span class="c1"># Fancy data processing here!</span> |
|
|
|
355 </code></pre></div> |
|
|
|
356 |
|
|
|
357 <p>However, there's one aspect many programmers have an opinion about but don't realize can be encoded into the function definition: <strong>How should callers specify each argument to the function?</strong> For the above function you'd likely document the following usages:</p> |
|
|
|
358 |
|
|
|
359 <div class="codehilite"><pre><span></span><code><span class="n">process_data</span><span class="p">(</span><span class="sa">b</span><span class="s2">&quot;input&quot;</span><span class="p">)</span> |
|
|
|
360 |
|
|
|
361 <span class="n">process_data</span><span class="p">(</span><span class="sa">b</span><span class="s2">&quot;input&quot;</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s2">&quot;utf-8&quot;</span><span class="p">)</span> |
|
|
|
362 </code></pre></div> |
|
|
|
363 |
|
|
|
364 <p>You don't need to specify <code>data=</code> for readers to infer what the first argument is likely to be. The parameter name is hinted by the function name: <code>process_data()</code>. On the other hand the <code>encoding</code> parameter isn't obvious if you only see the argument value. Given this I would recommend using a keyword argument for <code>encoding</code>.</p> |
|
|
|
365 |
|
|
|
366 <p>The above decisions make sense to me having written lots of Python, but what about beginners to Python or the library? <strong>Function parameters don't explain "how" to pass arguments.</strong> Whether an argument is passed as a positional argument or keyword argument is <em>usually</em> up to the caller. Below are all the ways to specify the same parameters, but many are likely not what the author intended:</p> |
|
|
|
367 |
|
|
|
368 <div class="codehilite"><pre><span></span><code><span class="c1"># All positional parameters, tougher to</span> |
|
|
|
369 <span class="c1"># infer the parameter for &#39;utf-8&#39;.</span> |
|
|
|
370 <span class="n">process_data</span><span class="p">(</span><span class="sa">b</span><span class="s2">&quot;input&quot;</span><span class="p">,</span> <span class="s2">&quot;utf-8&quot;</span><span class="p">)</span> |
|
|
|
371 |
|
|
|
372 <span class="c1"># Using `data` as keyword argument, but</span> |
|
|
|
373 <span class="c1"># not as clean as &quot;data&quot; term is duplicated.</span> |
|
|
|
374 <span class="n">process_data</span><span class="p">(</span><span class="n">data</span><span class="o">=</span><span class="sa">b</span><span class="s2">&quot;input&quot;</span><span class="p">)</span> |
|
|
|
375 <span class="n">process_data</span><span class="p">(</span><span class="n">data</span><span class="o">=</span><span class="sa">b</span><span class="s2">&quot;input&quot;</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s2">&quot;utf-8&quot;</span><span class="p">)</span> |
|
|
|
376 |
|
|
|
377 <span class="c1"># All keyword parameters but encoding</span> |
|
|
|
378 <span class="c1"># and data are flip-flopped.</span> |
|
|
|
379 <span class="n">process_data</span><span class="p">(</span><span class="n">encoding</span><span class="o">=</span><span class="s2">&quot;utf-8&quot;</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="sa">b</span><span class="s2">&quot;input&quot;</span><span class="p">)</span> |
|
|
|
380 </code></pre></div> |
|
|
|
381 |
|
|
|
382 <p>If the code is widespread enough you're almost guaranteed that <a href="https://xkcd.com/1172">someone is using your code in a way you didn't intend</a>. Let's see two Python features you can use to avoid this problem: </p> |
|
|
|
383 |
|
|
|
384 <h2>Keyword-only parameters</h2> |
|
|
|
385 |
|
|
|
386 <p><a href="https://www.python.org/dev/peps/pep-3102">PEP 3102</a> introduced this language feature in 2006 for Python 3.0 and later. Despite being in a ecosystem without Python 2 for two years I'm surprised how little I see this feature.</p> |
|
|
|
387 |
|
|
|
388 <p>Defining a parameter as being "keyword-only" looks like this:</p> |
|
|
|
389 |
|
|
|
390 <div class="codehilite"><pre><span></span><code><span class="k">def</span> <span class="nf">process_data</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s2">&quot;ascii&quot;</span><span class="p">):</span> <span class="o">...</span> |
|
|
|
391 </code></pre></div> |
|
|
|
392 |
|
|
|
393 <p>Notice the <code>*</code> between <code>data</code> and <code>encoding</code>? The asterisk means that <strong>all parameters to the right in the function signature can't be passed as positional arguments</strong>. These parameters are now "keyword-only".</p> |
|
|
|
394 |
|
|
|
395 <p>Now that the <code>encoding</code> parameter is a keyword-only how does the list of potential usages change?</p> |
|
|
|
396 |
|
|
|
397 <div class="codehilite"><pre><span></span><code><span class="c1"># The way you want users to use the function:</span> |
|
|
|
398 <span class="n">process_data</span><span class="p">(</span><span class="sa">b</span><span class="s2">&quot;input&quot;</span><span class="p">)</span> |
|
|
|
399 <span class="n">process_data</span><span class="p">(</span><span class="sa">b</span><span class="s2">&quot;input&quot;</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s2">&quot;utf-8&quot;</span><span class="p">)</span> |
|
|
|
400 |
|
|
|
401 <span class="c1"># Raises a TypeError:</span> |
|
|
|
402 <span class="n">process_data</span><span class="p">(</span><span class="sa">b</span><span class="s2">&quot;input&quot;</span><span class="p">,</span> <span class="s2">&quot;utf-8&quot;</span><span class="p">)</span> |
|
|
|
403 |
|
|
|
404 <span class="c1"># What way can (and will) use the function:</span> |
|
|
|
405 <span class="n">process_data</span><span class="p">(</span><span class="n">data</span><span class="o">=</span><span class="sa">b</span><span class="s2">&quot;input&quot;</span><span class="p">)</span> |
|
|
|
406 <span class="n">process_data</span><span class="p">(</span><span class="n">data</span><span class="o">=</span><span class="sa">b</span><span class="s2">&quot;input&quot;</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s2">&quot;utf-8&quot;</span><span class="p">)</span> |
|
|
|
407 <span class="n">process_data</span><span class="p">(</span><span class="n">encoding</span><span class="o">=</span><span class="s2">&quot;utf-8&quot;</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="sa">b</span><span class="s2">&quot;input&quot;</span><span class="p">)</span> |
|
|
|
408 </code></pre></div> |
|
|
|
409 |
|
|
|
410 <p>It's a small improvement but there's more we can do!</p> |
|
|
|
411 |
|
|
|
412 <h2>Positional-only parameters</h2> |
|
|
|
413 |
|
|
|
414 <p><a href="https://www.python.org/dev/peps/pep-0570">PEP 570</a> introduced another feature for specifying how to pass arguments. This feature landed in Python 3.8 so you may not be able to use it in projects supporting Python 3.7 <a href="https://endoflife.date/python">until mid-2023</a>.</p> |
|
|
|
415 |
|
|
|
416 <p>You can define "positional-only" argument in Python like so:</p> |
|
|
|
417 |
|
|
|
418 <div class="codehilite"><pre><span></span><code><span class="k">def</span> <span class="nf">process_data</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="o">/</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s2">&quot;ascii&quot;</span><span class="p">):</span> <span class="o">...</span> |
|
|
|
419 </code></pre></div> |
|
|
|
420 |
|
|
|
421 <p>The <code>/</code> in the function signature means that all parameters to the left of the <code>/</code> are positional-only. Positional-only parameters can't be passed a keyword argument:</p> |
|
|
|
422 |
|
|
|
423 <div class="codehilite"><pre><span></span><code><span class="c1"># This will raise a TypeError:</span> |
|
|
|
424 <span class="n">process_data</span><span class="p">(</span><span class="n">data</span><span class="o">=</span><span class="sa">b</span><span class="s2">&quot;input&quot;</span><span class="p">)</span> |
|
|
|
425 </code></pre></div> |
|
|
|
426 |
|
|
|
427 <p>Many functions in the standard library don't follow the typical rules for parameters. The example used in PEP 570 is the <a href="https://docs.python.org/3/library/functions.html#pow"><code>pow()</code> function</a>. When called with keyword arguments <code>pow()</code> will fail because the underlying C implementation only accepts positional arguments:</p> |
|
|
|
428 |
|
|
|
429 <div class="codehilite"><pre><span></span><code><span class="c1"># The `help()` output for `pow()` used</span> |
|
|
|
430 <span class="c1"># the `/` character even before Python</span> |
|
|
|
431 <span class="c1"># 3.8 implemented PEP 570:</span> |
|
|
|
432 <span class="o">&gt;&gt;&gt;</span> <span class="n">help</span><span class="p">(</span><span class="nb">pow</span><span class="p">)</span> |
|
|
|
433 <span class="o">...</span> |
|
|
|
434 <span class="nb">pow</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">/</span><span class="p">)</span> |
|
|
|
435 <span class="o">...</span> |
|
|
|
436 |
|
|
|
437 <span class="o">&gt;&gt;&gt;</span> <span class="nb">pow</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span> |
|
|
|
438 <span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span> |
|
|
|
439 <span class="n">File</span> <span class="s2">&quot;&lt;stdin&gt;&quot;</span><span class="p">,</span> <span class="n">line</span> <span class="mi">1</span><span class="p">,</span> <span class="ow">in</span> <span class="o">&lt;</span><span class="n">module</span><span class="o">&gt;</span> |
|
|
|
440 <span class="ne">TypeError</span><span class="p">:</span> <span class="nb">pow</span><span class="p">()</span> <span class="n">takes</span> <span class="n">no</span> <span class="n">keyword</span> <span class="n">arguments</span> |
|
|
|
441 </code></pre></div> |
|
|
|
442 |
|
|
|
443 <h2>Putting it all together</h2> |
|
|
|
444 |
|
|
|
445 <p>You can use both positional-only and keyword-only arguments together in the same function signature:</p> |
|
|
|
446 |
|
|
|
447 <div class="codehilite"><pre><span></span><code><span class="k">def</span> <span class="nf">process_data</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="o">/</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s2">&quot;ascii&quot;</span><span class="p">):</span> <span class="o">...</span> |
|
|
|
448 </code></pre></div> |
|
|
|
449 |
|
|
|
450 <p>And now with <code>data</code> being positional-only and <code>encoding</code> keyword-only let's look at how our function can be used:</p> |
|
|
|
451 |
|
|
|
452 <div class="codehilite"><pre><span></span><code><span class="c1"># The way you want users to use the function:</span> |
|
|
|
453 <span class="n">process_data</span><span class="p">(</span><span class="sa">b</span><span class="s2">&quot;input&quot;</span><span class="p">)</span> |
|
|
|
454 <span class="n">process_data</span><span class="p">(</span><span class="sa">b</span><span class="s2">&quot;input&quot;</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s2">&quot;utf-8&quot;</span><span class="p">)</span> |
|
|
|
455 |
|
|
|
456 <span class="c1"># Raises a TypeError:</span> |
|
|
|
457 <span class="n">process_data</span><span class="p">(</span><span class="sa">b</span><span class="s2">&quot;input&quot;</span><span class="p">,</span> <span class="s2">&quot;utf-8&quot;</span><span class="p">)</span> |
|
|
|
458 <span class="n">process_data</span><span class="p">(</span><span class="n">data</span><span class="o">=</span><span class="sa">b</span><span class="s2">&quot;input&quot;</span><span class="p">)</span> |
|
|
|
459 <span class="n">process_data</span><span class="p">(</span><span class="n">data</span><span class="o">=</span><span class="sa">b</span><span class="s2">&quot;input&quot;</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s2">&quot;utf-8&quot;</span><span class="p">)</span> |
|
|
|
460 <span class="n">process_data</span><span class="p">(</span><span class="n">encoding</span><span class="o">=</span><span class="s2">&quot;utf-8&quot;</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="sa">b</span><span class="s2">&quot;input&quot;</span><span class="p">)</span> |
|
|
|
461 </code></pre></div> |
|
|
|
462 |
|
|
|
463 <p><strong>Success!!</strong> π Your function now only allows specifying arguments as intended.</p> |
|
|
|
464 |
|
|
|
465 <h2>Why use strict function signatures?</h2> |
|
|
|
466 |
|
|
|
467 <p>So why go through this extra bit of trouble? You could read the "motivation" sections of <a href="https://www.python.org/dev/peps/pep-3102/#rationale">PEP 3102</a> and <a href="https://www.python.org/dev/peps/pep-0570/#motivation">PEP-570</a> for some of the reasons why these features are useful. Below are a few reasons that I think are important from an API design perspective:</p> |
|
|
|
468 |
|
|
|
469 <h3>Less to consider when your function changes</h3> |
|
|
|
470 |
|
|
|
471 <p>Here's a real-life example I had to handle with the <a href="https://github.com/elastic/elasticsearch-py">Elasticsearch Python client</a>. We have an API method called <code>get()</code> which fetches a document from Elasticsearch by its ID. The function signature was going to change in v8.0.0 due to the <code>doc_type</code> parameter being deprecated server-side in v7.0.0 and scheduled for removal in v8.0.0.</p> |
|
|
|
472 |
|
|
|
473 <div class="codehilite"><pre><span></span><code><span class="c1"># Function signature in v7.16.0</span> |
|
|
|
474 <span class="k">def</span> <span class="nf">get</span><span class="p">(</span><span class="n">index</span><span class="p">,</span> <span class="nb">id</span><span class="p">,</span> <span class="n">doc_type</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">params</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">...</span><span class="p">):</span> <span class="o">...</span> |
|
|
|
475 |
|
|
|
476 <span class="c1"># Function signature in v8.0.0</span> |
|
|
|
477 <span class="k">def</span> <span class="nf">get</span><span class="p">(</span><span class="n">index</span><span class="p">,</span> <span class="nb">id</span><span class="p">,</span> <span class="n">params</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">...</span><span class="p">):</span> <span class="o">...</span> |
|
|
|
478 </code></pre></div> |
|
|
|
479 |
|
|
|
480 <p>If the <code>doc_type</code> parameter were removed without mitigation, code using <code>get()</code> would change between v7.16 and v8.0.0:</p> |
|
|
|
481 |
|
|
|
482 <div class="codehilite"><pre><span></span><code><span class="n">client</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;1&quot;</span><span class="p">,</span> <span class="s2">&quot;2&quot;</span><span class="p">,</span> <span class="s2">&quot;3&quot;</span><span class="p">)</span> |
|
|
|
483 |
|
|
|
484 <span class="c1"># In 7.16.0 the above arguments will</span> |
|
|
|
485 <span class="c1"># be assigned like so:</span> |
|
|
|
486 |
|
|
|
487 <span class="c1"># {index=1, id=2, doc_type=3}</span> |
|
|
|
488 |
|
|
|
489 <span class="c1"># In 8.0.0 (if not mitigated) the above</span> |
|
|
|
490 <span class="c1"># arguments would be assigned like so:</span> |
|
|
|
491 |
|
|
|
492 <span class="c1"># {index=1, id=2, params=3} (not good!)</span> |
|
|
|
493 </code></pre></div> |
|
|
|
494 |
|
|
|
495 <p>We started emitting a <code>DeprecationWarning</code> whenever <code>doc_type</code> was used, but warnings are opt-in and can be missed. So in addition to deprecating parameters we decided to deprecate using positional arguments and require using only keyword arguments for all Elasticsearch API methods in v8.0.0. <strong>Now parameters can be added and removed without considering the parameters' position in previous versions.</strong></p> |
|
|
|
496 |
|
|
|
497 <p>This change also meant the API generator logic could be greatly simplified because the generator no longer needed to account for the order parameters were previously generated with.</p> |
|
|
|
498 |
|
|
|
499 <p><strong>There's additional API freedoms when using positional-only arguments too.</strong> Recall the <code>process_data()</code> function defined above:</p> |
|
|
|
500 |
|
|
|
501 <div class="codehilite"><pre><span></span><code><span class="k">def</span> <span class="nf">process_data</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="o">/</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s2">&quot;utf-8&quot;</span><span class="p">):</span> <span class="o">...</span> |
|
|
|
502 </code></pre></div> |
|
|
|
503 |
|
|
|
504 <p>If you now wanted the <code>data</code> parameter to accept either a single <code>bytes</code> instance or a list of <code>bytes</code> instances you might want to rename the parameter to better represent the accepted types. <strong>If <code>data</code> is a positional-only parameter then you can rename the parameter without breaking anyone</strong>. Without being a positional-only argument you risk breaking users specifying <code>data</code> with a keyword argument:</p> |
|
|
|
505 |
|
|
|
506 <div class="codehilite"><pre><span></span><code><span class="c1"># You can rename &#39;data&#39; -&gt; &#39;data_or_list&#39;</span> |
|
|
|
507 <span class="c1"># without breaking anyone&#39;s code.</span> |
|
|
|
508 <span class="k">def</span> <span class="nf">process_data</span><span class="p">(</span><span class="n">data_or_list</span><span class="p">,</span> <span class="o">/</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s2">&quot;utf-8&quot;</span><span class="p">):</span> <span class="o">...</span> |
|
|
|
509 </code></pre></div> |
|
|
|
510 |
|
|
|
511 <p>For more information there's an <a href="https://www.python.org/dev/peps/pep-0570/#id27">"Empowering Library Authors" section in PEP 570</a> that details other cases.</p> |
|
|
|
512 |
|
|
|
513 <h3>Consistency between documentation and usage</h3> |
|
|
|
514 |
|
|
|
515 <p>Ideally documentation will pick a single way of using each function and be consistent within itself. <strong>Why not require users to use functions as they are documented?</strong> If urllib3 was being written today the function signature for <code>request()</code> might look like this with <code>method</code> and <code>url</code> being positional-only and all other parameters being keyword-only:</p> |
|
|
|
516 |
|
|
|
517 <div class="codehilite"><pre><span></span><code><span class="k">def</span> <span class="nf">request</span><span class="p">(</span><span class="n">method</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="o">/</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">...</span><span class="p">):</span> <span class="o">...</span> |
|
|
|
518 </code></pre></div> |
|
|
|
519 |
|
|
|
520 <p>This function is found <em>everywhere</em>, even across other HTTP client libraries like Requests and aiohttp, so is likely to be understandable to users who have never used urllib3.</p> |
|
|
|
521 |
|
|
|
522 <div class="codehilite"><pre><span></span><code><span class="c1"># We&#39;re used to seeing this everywhere:</span> |
|
|
|
523 <span class="n">request</span><span class="p">(</span><span class="s2">&quot;GET&quot;</span><span class="p">,</span> <span class="s2">&quot;https://example.com&quot;</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="p">{</span><span class="o">...</span><span class="p">})</span> |
|
|
|
524 |
|
|
|
525 <span class="c1"># These aren&#39;t as immediately recognizable:</span> |
|
|
|
526 <span class="n">request</span><span class="p">(</span><span class="n">method</span><span class="o">=</span><span class="s2">&quot;GET&quot;</span><span class="p">,</span> <span class="n">url</span><span class="o">=</span><span class="s2">&quot;https://example.com&quot;</span><span class="p">)</span> |
|
|
|
527 <span class="n">request</span><span class="p">(</span><span class="s2">&quot;GET&quot;</span><span class="p">,</span> <span class="s2">&quot;https://example.com&quot;</span><span class="p">,</span> <span class="p">{</span><span class="o">...</span><span class="p">})</span> |
|
|
|
528 </code></pre></div> |
|
|
|
529 |
|
|
|
530 <p>By having a strict function signature we can ensure code written by users will look recognizable to future readers.</p> |
|
|
|
531 |
|
|
|
532 </div> |
|
|
|
533 </div> |
|
|
|
534 <div class="row"> |
|
|
|
535 <div class="col-12"> |
|
|
|
536 <center> |
|
|
|
537 <div class="how-to-subscribe"> |
|
|
|
538 Enjoy this post? <span class="heart">β€&#xFE0E</span> Subscribe for more via <a href="https://tinyletter.com/sethmlarson">the newsletter</a> or <a href="/feed">RSS</a> |
|
|
|
539 </div> |
|
|
|
540 </center> |
|
|
|
541 </div> |
|
|
|
542 </div> |
|
|
|
543 |
|
|
|
544 <div class="row"> |
|
|
|
545 <div class="col-2"></div> |
|
|
|
546 <div class="col-8"><center><small>Built with <a href="https://simplegrid.io" target="_blank" rel="nofollow noopener noreferrer">SimpleGrid</a>, <a href="https://simplegrid.io/" target="_blank" rel="nofollow noopener noreferrer">FontAwesome</a>, <a href="https://flask.palletsprojects.com" target="_blank" rel="nofollow noopener noreferrer">Flask</a>, and <a href="https://github.com/sethmlarson/sethmlarson.dev" target="_blank" rel="nofollow noopener noreferrer">more</a>.</small></center></div> |
|
|
|
547 <div class="col-2"></div> |
|
|
|
548 </div> |
|
|
|
549 </div> |
|
|
|
550 |
|
|
|
551 <!-- Google Analytics --> |
|
|
|
552 <script async src="https://www.googletagmanager.com/gtag/js?id=G-C3VD7T243W"></script> |
|
|
|
553 <script> |
|
|
|
554 window.dataLayer = window.dataLayer || []; |
|
|
|
555 function gtag(){dataLayer.push(arguments);} |
|
|
|
556 gtag('js', new Date()); |
|
|
|
557 gtag('config', 'G-C3VD7T243W'); |
|
|
|
558 </script> |
|
|
|
559 </body> |
|
|
|
560 </html></content> |
|
|
|
561 </entry> |
|
|
|
562 <entry xml:base="http://sethmlarson.dev/feed"> |
|
|
|
563 <title type="text">Problems with testing Python pre-releases and pip caching</title> |
|
|
|
564 <id>http://sethmlarson.dev/blog/python-prereleases-and-pip-cache?date=2022-01-13</id> |
|
|
|
565 <updated>2022-01-13T00:00:00Z</updated> |
|
|
|
566 <published>2022-01-13T00:00:00Z</published> |
|
|
|
567 <link href="http://sethmlarson.dev/blog/python-prereleases-and-pip-cache?date=2022-01-13" /> |
|
|
|
568 <author> |
|
|
|
569 <name>Seth Michael Larson</name> |
|
|
|
570 </author> |
|
|
|
571 <content type="html"><!DOCTYPE html> |
|
|
|
572 <html lang="en"> |
|
|
|
573 <head> |
|
|
|
574 <meta charset="utf-8"> |
|
|
|
575 <title>Problems with testing Python pre-releases and pip caching</title> |
|
|
|
576 <meta name="description" content="Blogging about Python and the Internet"> |
|
|
|
577 <meta name="keywords" content="blog python open source http networking security"> |
|
|
|
578 <meta name="author" content="Seth Michael Larson"> |
|
|
|
579 <meta name="viewport" content="width=device-width, initial-scale=1"> |
|
|
|
580 <meta name="format-detection" content="telephone=no"/> |
|
|
|
581 <link rel="alternate" type="application/rss+xml" title="RSS Feed" href="/feed"/> |
|
|
|
582 <link rel="icon" href="/static/favicon.ico"> |
|
|
|
583 <link rel="stylesheet" href="/static/style.css"> |
|
|
|
584 |
|
|
|
585 <meta property="og:site_name" content="Seth Michael Larson"/> |
|
|
|
586 <meta property="og:author" content="Seth Michael Larson"/> |
|
|
|
587 <meta property="og:type" content="article"/> |
|
|
|
588 <meta property="og:title" content="Problems with testing Python pre-releases and pip caching"/> |
|
|
|
589 <meta property="og:description" content="Some time ago the urllib3 team noticed that our Python 3.11 test suite started failing with a strange error. On GitHub Actions all we could see was: |
|
|
|
590 |
|
|
|
591 nox &amp;gt; Running session test-3.11 |
|
|
|
592 nox &amp;gt; Cre..."/> |
|
|
|
593 <meta property="og:image" content="http://sethmlarson.dev/static/avatar.jpeg"/> |
|
|
|
594 <meta name="twitter:card" content="summary"/> |
|
|
|
595 <meta name="twitter:site" content="@sethmlarson"/> |
|
|
|
596 <meta name="twitter:creator" content="@sethmlarson"/> |
|
|
|
597 <meta name="twitter:title" content="Problems with testing Python pre-releases and pip caching"/> |
|
|
|
598 <meta name="twitter:description" content="Some time ago the urllib3 team noticed that our Python 3.11 test suite started failing with a strange error. On GitHub Actions all we could see was: |
|
|
|
599 |
|
|
|
600 nox &amp;gt; Running session test-3.11 |
|
|
|
601 nox &amp;gt; Cre..."/> |
|
|
|
602 <meta property="og:image" content="http://sethmlarson.dev/static/avatar.jpeg"/> |
|
|
|
603 |
|
|
|
604 </head> |
|
|
|
605 <body> |
|
|
|
606 <div class="container"> |
|
|
|
607 <div class="row"> |
|
|
|
608 <div class="col-6"> |
|
|
|
609 <center> |
|
|
|
610 <h1 style="margin-bottom: 0.1em; font-size: 1.8em;">Seth Michael Larson</h1> |
|
|
|
611 <span style="font-style: italic;">Blogging about Python and the Internet</span> |
|
|
|
612 </center> |
|
|
|
613 </div> |
|
|
|
614 <div class="col-6"> |
|
|
|
615 <div class="navbar-outer"> |
|
|
|
616 <div class="navbar-inner"> |
|
|
|
617 <a class="icon" href="/about"> |
|
|
|
618 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"> |
|
|
|
619 <title>About</title><path d="M528 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h480c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-352 96c35.3 0 64 28.7 64 64s-28.7 64-64 64-64-28.7-64-64 28.7-64 64-64zm112 236.8c0 10.6-10 19.2-22.4 19.2H86.4C74 384 64 375.4 64 364.8v-19.2c0-31.8 30.1-57.6 67.2-57.6h5c12.3 5.1 25.7 8 39.8 8s27.6-2.9 39.8-8h5c37.1 0 67.2 25.8 67.2 57.6v19.2zM512 312c0 4.4-3.6 8-8 8H360c-4.4 0-8-3.6-8-8v-16c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16zm0-64c0 4.4-3.6 8-8 8H360c-4.4 0-8-3.6-8-8v-16c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16zm0-64c0 4.4-3.6 8-8 8H360c-4.4 0-8-3.6-8-8v-16c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16z"/> |
|
|
|
620 </svg> |
|
|
|
621 </a> |
|
|
|
622 <a class="icon" href="/blog"> |
|
|
|
623 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> |
|
|
|
624 <title>Blog</title><path d="M172.2 226.8c-14.6-2.9-28.2 8.9-28.2 23.8V301c0 10.2 7.1 18.4 16.7 22 18.2 6.8 31.3 24.4 31.3 45 0 26.5-21.5 48-48 48s-48-21.5-48-48V120c0-13.3-10.7-24-24-24H24c-13.3 0-24 10.7-24 24v248c0 89.5 82.1 160.2 175 140.7 54.4-11.4 98.3-55.4 109.7-109.7 17.4-82.9-37-157.2-112.5-172.2zM209 0c-9.2-.5-17 6.8-17 16v31.6c0 8.5 6.6 15.5 15 15.9 129.4 7 233.4 112 240.9 241.5.5 8.4 7.5 15 15.9 15h32.1c9.2 0 16.5-7.8 16-17C503.4 139.8 372.2 8.6 209 0zm.3 96c-9.3-.7-17.3 6.7-17.3 16.1v32.1c0 8.4 6.5 15.3 14.8 15.9 76.8 6.3 138 68.2 144.9 145.2.8 8.3 7.6 14.7 15.9 14.7h32.2c9.3 0 16.8-8 16.1-17.3-8.4-110.1-96.5-198.2-206.6-206.7z"/> |
|
|
|
625 </svg> |
|
|
|
626 </a> |
|
|
|
627 <a class="icon" href="https://twitter.com/sethmlarson" target="_blank" rel="nofollow noopener noreferrer"> |
|
|
|
628 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> |
|
|
|
629 <title>Twitter</title><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/> |
|
|
|
630 </svg> |
|
|
|
631 </a> |
|
|
|
632 <a class="icon" href="https://github.com/sethmlarson" target="_blank" rel="nofollow noopener noreferrer"> |
|
|
|
633 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"> |
|
|
|
634 <title>GitHub</title><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/> |
|
|
|
635 </svg> |
|
|
|
636 </a> |
|
|
|
637 <a class="icon" href="https://linkedin.com/in/sethmlarson" target="_blank" rel="nofollow noopener noreferrer"> |
|
|
|
638 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"> |
|
|
|
639 <title>LinkedIn</title><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3zM135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5zm282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9V416z"/> |
|
|
|
640 </svg> |
|
|
|
641 </a> |
|
|
|
642 </div> |
|
|
|
643 </div> |
|
|
|
644 </div> |
|
|
|
645 </div> |
|
|
|
646 |
|
|
|
647 <div class="row"> |
|
|
|
648 <div class="col-12"> |
|
|
|
649 <h2 class="blog-title" style="text-align: center">Problems with testing Python pre-releases and pip caching</h2> |
|
|
|
650 <p><center>Published 2022-01-13 β <span class="heart">β€&#xFE0E</span> Subscribe for more via <a href="https://tinyletter.com/sethmlarson">the newsletter</a> or <a href="/feed">RSS</a></center></p> |
|
|
|
651 </div> |
|
|
|
652 </div> |
|
|
|
653 <div class="row"> |
|
|
|
654 <div class="col-12"> |
|
|
|
655 <p>Some time ago the urllib3 team noticed that our Python 3.11 test suite started failing with a strange error. On GitHub Actions all we could see was:</p> |
|
|
|
656 |
|
|
|
657 <div class="codehilite"><pre><span></span><code>nox &gt; Running session test-3.11 |
|
|
|
658 nox &gt; Creating virtual environment <span class="o">(</span>virtualenv<span class="o">)</span> using python3.11 <span class="k">in</span> .nox/test-3-11 |
|
|
|
659 nox &gt; python --version |
|
|
|
660 Python <span class="m">3</span>.11.0a3 |
|
|
|
661 nox &gt; Command coverage run --parallel-mode -m pytest -r a |
|
|
|
662 --color<span class="o">=</span>yes --tb<span class="o">=</span>native --no-success-flaky-report test/ |
|
|
|
663 failed with <span class="nb">exit</span> code -11 |
|
|
|
664 |
|
|
|
665 nox &gt; Session test-3.11 failed. |
|
|
|
666 Error: Process completed with <span class="nb">exit</span> code <span class="m">1</span>. |
|
|
|
667 </code></pre></div> |
|
|
|
668 |
|
|
|
669 <p>Notice that our test execution was exited with a return code of <code>-11</code> which corresponds to signal <code>SIGSEGV</code> also known as a segmentation fault. This means that somewhere in C-land an improper memory location was being accessed, not good! Without a better traceback we wouldn't be able to know where the error is occuring.</p> |
|
|
|
670 |
|
|
|
671 <p><a href="https://github.com/pquentin">Quentin</a> and I both attempted to recreate the error locally with mixed results. I wasn't able to reproduce the error but Quentin was able to reproduce the error with tracebacks that were happening in both the <code>ssl</code> and <code>selectors</code> modules:</p> |
|
|
|
672 |
|
|
|
673 <div class="codehilite"><pre><span></span><code>test/test_reproduce.py Fatal Python error: Segmentation fault |
|
|
|
674 |
|
|
|
675 Thread 0x00007fee9a250640 <span class="o">(</span>most recent call first<span class="o">)</span>: |
|
|
|
676 File <span class="s2">&quot;/home/install/lib/python3.11/ssl.py&quot;</span>, line <span class="m">1346</span> <span class="k">in</span> do_handshake |
|
|
|
677 File <span class="s2">&quot;/home/urllib3/venv/lib/python3.11/site-packages/tornado/iostream.py&quot;</span>, line <span class="m">1391</span> <span class="k">in</span> _do_ssl_handshake |
|
|
|
678 File <span class="s2">&quot;/home/urllib3/venv/lib/python3.11/site-packages/tornado/iostream.py&quot;</span>, line <span class="m">1478</span> <span class="k">in</span> _handle_read |
|
|
|
679 File <span class="s2">&quot;/home/urllib3/venv/lib/python3.11/site-packages/tornado/iostream.py&quot;</span>, line <span class="m">696</span> <span class="k">in</span> _handle_events |
|
|
|
680 File <span class="s2">&quot;/home/urllib3/venv/lib/python3.11/site-packages/tornado/platform/asyncio.py&quot;</span>, line <span class="m">189</span> <span class="k">in</span> _handle_events |
|
|
|
681 File <span class="s2">&quot;/home/install/lib/python3.11/asyncio/events.py&quot;</span>, line <span class="m">80</span> <span class="k">in</span> _run |
|
|
|
682 File <span class="s2">&quot;/home/install/lib/python3.11/asyncio/base_events.py&quot;</span>, line <span class="m">1858</span> <span class="k">in</span> _run_once |
|
|
|
683 File <span class="s2">&quot;/home/install/lib/python3.11/asyncio/base_events.py&quot;</span>, line <span class="m">591</span> <span class="k">in</span> run_forever |
|
|
|
684 File <span class="s2">&quot;/home/urllib3/venv/lib/python3.11/site-packages/tornado/platform/asyncio.py&quot;</span>, line <span class="m">199</span> <span class="k">in</span> start |
|
|
|
685 File <span class="s2">&quot;/home/install/lib/python3.11/threading.py&quot;</span>, line <span class="m">968</span> <span class="k">in</span> run |
|
|
|
686 File <span class="s2">&quot;/home/install/lib/python3.11/threading.py&quot;</span>, line <span class="m">1031</span> <span class="k">in</span> _bootstrap_inner |
|
|
|
687 File <span class="s2">&quot;/home/install/lib/python3.11/threading.py&quot;</span>, line <span class="m">988</span> <span class="k">in</span> _bootstrap |
|
|
|
688 |
|
|
|
689 Extension modules: tornado.speedups, _brotli, _cffi_backend <span class="o">(</span>total: <span class="m">3</span><span class="o">)</span> |
|
|
|
690 zsh: segmentation fault <span class="o">(</span>core dumped<span class="o">)</span> pytest |
|
|
|
691 </code></pre></div> |
|
|
|
692 |
|
|
|
693 <p>This looks like an issue in CPython, but we'll eventually discover this error was being caused by our pip cache!</p> |
|
|
|
694 |
|
|
|
695 <h2>Finding and reporting the "bug"</h2> |
|
|
|
696 |
|
|
|
697 <p>After we could reproduce the error reliably, Quentin started <a href="https://www.metaltoad.com/blog/beginners-guide-git-bisect-process-elimination">git bisecting CPython</a> to find the exact commit that introduced the issue. The error was narrowed down to <a href="https://github.com/python/cpython/commit/32a67246b0d1e08cd50fc3bfa58052cfeb515b2e">this single commit</a> and after seeing that the PR mentioned that "there should be zero change in behavior" thus <a href="https://bugs.python.org/issue46320">an issue was opened on the Python issue tracker</a> (BPO) to report what we'd been experiencing.</p> |
|
|
|
698 |
|
|
|
699 <p>Within this issue <a href="https://github.com/ericsnowcurrently">Eric Snow</a> (who was the author of the commit in question) answered quickly and was able to reproduce the error, however he mentioned that the commit changed CPython's Application Binary Interface (ABI) and after slightly rearranging the <code>PyThreadState</code> struct was able to make the error go away. Then Eric asked this critical question:</p> |
|
|
|
700 |
|
|
|
701 <blockquote> |
|
|
|
702 <p>Could it be that the wheel for one or more the dependencies was built against an earlier 3.11 release (with the previous PyThreadState layout)?</p> |
|
|
|
703 </blockquote> |
|
|
|
704 |
|
|
|
705 <p><strong>The answer to this was yes!</strong> Pip was caching a wheel built using CFFI and Python 3.11.0-alpha2 and was installing that same wheel for the now Python 3.11.0-alpha3 both on our local machines and in our test suite. By clearing the pip cache on our machines and our CI we were able to get a passing test suite. π Thanks Eric!</p> |
|
|
|
706 |
|
|
|
707 <h2>When should you be testing Python pre-releases?</h2> |
|
|
|
708 |
|
|
|
709 <p>Testing your code against pre-releases of Python is important to ensure a smooth upgrade for both your upstream dependencies and your downstream users. <strong>This is especially the case for release candidate builds of Python.</strong></p> |
|
|
|
710 |
|
|
|
711 <p>Eric noted in the issue we filed:</p> |
|
|
|
712 |
|
|
|
713 <blockquote> |
|
|
|
714 <p>Thanks for testing against the alpha releases!!! You're having a positive impact.</p> |
|
|
|
715 </blockquote> |
|
|
|
716 |
|
|
|
717 <p>However, doing so super early on in the development cycle of a new Python version (like during the alpha or beta phases) comes with a few potential pitfalls, including running into ABI issues like the one mentioned above and needing to build binary dependencies from source distributions instead of wheels which can increase test suite execution time. <strong>Figure out what is sustainable and makes sense for your project.</strong></p> |
|
|
|
718 |
|
|
|
719 <p>If you maintain a Python library you should try at least to manually run your test suite once when the <strong>first release candidate is published</strong>. This means there's still time for the Python core team to fix issues and you're unlikely to run into strangeness like ABI changes between pre-releases.</p> |
|
|
|
720 |
|
|
|
721 <p>The urllib3 team tries to start testing against in-development Python versions as soon as they're available given our unique position near the top of most dependency chains.</p> |
|
|
|
722 |
|
|
|
723 <h3>When should you be aware of ABI changes?</h3> |
|
|
|
724 |
|
|
|
725 <p>Unless you're testing alpha and beta releases you likely won't have to think about the Python ABI changing. Technically it's acceptable for the Python core devs to change the ABI between <strong>release candidates</strong>, but this is much less likely than in between alphas and betas.</p> |
|
|
|
726 |
|
|
|
727 <h2>What are we doing to make this better?</h2> |
|
|
|
728 |
|
|
|
729 <p>Our team was using the <a href="https://github.com/actions/setup-python">setup-python GitHub Action</a> which recently added support for automatically caching installed pip dependencies between runs. Because this GitHub Action is very popular we wanted to make testing pre-releases of Python easier by avoiding potential foot-guns like the one above.</p> |
|
|
|
730 |
|
|
|
731 <p>We knew that pip's cache shouldn't be re-used across, at a minimum, different pre-release versions. We <a href="https://github.com/actions/setup-python/issues/319">opened an issue</a> on the repository which was quickly noticed by <a href="https://github.com/hugovk">Hugo van Kemenade</a> who had a <a href="https://github.com/actions/setup-python/pull/303">similar issue open</a> to add the <strong>requested Python version</strong> (i.e. in YAML <code>python: "3.9"</code>) to the "cache key".</p> |
|
|
|
732 |
|
|
|
733 <p>A "cache key" is the identifier that the setup-python action uses to lookup the archived pip cache so any changes to the cache key between two runs would essentially "invalidate" the cache and force pip to reinstall without cached dependencies. We discussed how our two issues were similar and could be solved by adding the <strong>fully qualified version number</strong> (i.e. <code>python --version</code> being <code>3.11.0a3</code>) to the cache key instead.</p> |
|
|
|
734 |
|
|
|
735 </div> |
|
|
|
736 </div> |
|
|
|
737 <div class="row"> |
|
|
|
738 <div class="col-12"> |
|
|
|
739 <center> |
|
|
|
740 <div class="how-to-subscribe"> |
|
|
|
741 Enjoy this post? <span class="heart">β€&#xFE0E</span> Subscribe for more via <a href="https://tinyletter.com/sethmlarson">the newsletter</a> or <a href="/feed">RSS</a> |
|
|
|
742 </div> |
|
|
|
743 </center> |
|
|
|
744 </div> |
|
|
|
745 </div> |
|
|
|
746 |
|
|
|
747 <div class="row"> |
|
|
|
748 <div class="col-2"></div> |
|
|
|
749 <div class="col-8"><center><small>Built with <a href="https://simplegrid.io" target="_blank" rel="nofollow noopener noreferrer">SimpleGrid</a>, <a href="https://simplegrid.io/" target="_blank" rel="nofollow noopener noreferrer">FontAwesome</a>, <a href="https://flask.palletsprojects.com" target="_blank" rel="nofollow noopener noreferrer">Flask</a>, and <a href="https://github.com/sethmlarson/sethmlarson.dev" target="_blank" rel="nofollow noopener noreferrer">more</a>.</small></center></div> |
|
|
|
750 <div class="col-2"></div> |
|
|
|
751 </div> |
|
|
|
752 </div> |
|
|
|
753 |
|
|
|
754 <!-- Google Analytics --> |
|
|
|
755 <script async src="https://www.googletagmanager.com/gtag/js?id=G-C3VD7T243W"></script> |
|
|
|
756 <script> |
|
|
|
757 window.dataLayer = window.dataLayer || []; |
|
|
|
758 function gtag(){dataLayer.push(arguments);} |
|
|
|
759 gtag('js', new Date()); |
|
|
|
760 gtag('config', 'G-C3VD7T243W'); |
|
|
|
761 </script> |
|
|
|
762 </body> |
|
|
|
763 </html></content> |
|
|
|
764 </entry> |
|
|
|
765 <entry xml:base="http://sethmlarson.dev/feed"> |
|
|
|
766 <title type="text">urllib3 raised $15,000 in 2021 (Newsletter #6)</title> |
|
|
|
767 <id>http://sethmlarson.dev/blog/urllib3-raised-15k-in-2021?date=2021-12-29</id> |
|
|
|
768 <updated>2021-12-29T00:00:00Z</updated> |
|
|
|
769 <published>2021-12-29T00:00:00Z</published> |
|
|
|
770 <link href="http://sethmlarson.dev/blog/urllib3-raised-15k-in-2021?date=2021-12-29" /> |
|
|
|
771 <author> |
|
|
|
772 <name>Seth Michael Larson</name> |
|
|
|
773 </author> |
|
|
|
774 <content type="html"><!DOCTYPE html> |
|
|
|
775 <html lang="en"> |
|
|
|
776 <head> |
|
|
|
777 <meta charset="utf-8"> |
|
|
|
778 <title>urllib3 raised $15,000 in 2021 (Newsletter #6)</title> |
|
|
|
779 <meta name="description" content="Blogging about Python and the Internet"> |
|
|
|
780 <meta name="keywords" content="blog python open source http networking security"> |
|
|
|
781 <meta name="author" content="Seth Michael Larson"> |
|
|
|
782 <meta name="viewport" content="width=device-width, initial-scale=1"> |
|
|
|
783 <meta name="format-detection" content="telephone=no"/> |
|
|
|
784 <link rel="alternate" type="application/rss+xml" title="RSS Feed" href="/feed"/> |
|
|
|
785 <link rel="icon" href="/static/favicon.ico"> |
|
|
|
786 <link rel="stylesheet" href="/static/style.css"> |
|
|
|
787 |
|
|
|
788 <meta property="og:site_name" content="Seth Michael Larson"/> |
|
|
|
789 <meta property="og:author" content="Seth Michael Larson"/> |
|
|
|
790 <meta property="og:type" content="article"/> |
|
|
|
791 <meta property="og:title" content="urllib3 raised $15,000 in 2021 (Newsletter #6)"/> |
|
|
|
792 <meta property="og:description" content="Welcome to the 6th urllib3 newsletter, end of 2021 edition! If you&#39;d like to discuss this edition of our newsletter you can join our community Discord. |
|
|
|
793 |
|
|
|
794 Thanks to our sponsors! |
|
|
|
795 |
|
|
|
796 This year we receiv..."/> |
|
|
|
797 <meta property="og:image" content="http://sethmlarson.dev/static/avatar.jpeg"/> |
|
|
|
798 <meta name="twitter:card" content="summary"/> |
|
|
|
799 <meta name="twitter:site" content="@sethmlarson"/> |
|
|
|
800 <meta name="twitter:creator" content="@sethmlarson"/> |
|
|
|
801 <meta name="twitter:title" content="urllib3 raised $15,000 in 2021 (Newsletter #6)"/> |
|
|
|
802 <meta name="twitter:description" content="Welcome to the 6th urllib3 newsletter, end of 2021 edition! If you&#39;d like to discuss this edition of our newsletter you can join our community Discord. |
|
|
|
803 |
|
|
|
804 Thanks to our sponsors! |
|
|
|
805 |
|
|
|
806 This year we receiv..."/> |
|
|
|
807 <meta property="og:image" content="http://sethmlarson.dev/static/avatar.jpeg"/> |
|
|
|
808 |
|
|
|
809 </head> |
|
|
|
810 <body> |
|
|
|
811 <div class="container"> |
|
|
|
812 <div class="row"> |
|
|
|
813 <div class="col-6"> |
|
|
|
814 <center> |
|
|
|
815 <h1 style="margin-bottom: 0.1em; font-size: 1.8em;">Seth Michael Larson</h1> |
|
|
|
816 <span style="font-style: italic;">Blogging about Python and the Internet</span> |
|
|
|
817 </center> |
|
|
|
818 </div> |
|
|
|
819 <div class="col-6"> |
|
|
|
820 <div class="navbar-outer"> |
|
|
|
821 <div class="navbar-inner"> |
|
|
|
822 <a class="icon" href="/about"> |
|
|
|
823 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"> |
|
|
|
824 <title>About</title><path d="M528 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h480c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-352 96c35.3 0 64 28.7 64 64s-28.7 64-64 64-64-28.7-64-64 28.7-64 64-64zm112 236.8c0 10.6-10 19.2-22.4 19.2H86.4C74 384 64 375.4 64 364.8v-19.2c0-31.8 30.1-57.6 67.2-57.6h5c12.3 5.1 25.7 8 39.8 8s27.6-2.9 39.8-8h5c37.1 0 67.2 25.8 67.2 57.6v19.2zM512 312c0 4.4-3.6 8-8 8H360c-4.4 0-8-3.6-8-8v-16c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16zm0-64c0 4.4-3.6 8-8 8H360c-4.4 0-8-3.6-8-8v-16c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16zm0-64c0 4.4-3.6 8-8 8H360c-4.4 0-8-3.6-8-8v-16c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16z"/> |
|
|
|
825 </svg> |
|
|
|
826 </a> |
|
|
|
827 <a class="icon" href="/blog"> |
|
|
|
828 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> |
|
|
|
829 <title>Blog</title><path d="M172.2 226.8c-14.6-2.9-28.2 8.9-28.2 23.8V301c0 10.2 7.1 18.4 16.7 22 18.2 6.8 31.3 24.4 31.3 45 0 26.5-21.5 48-48 48s-48-21.5-48-48V120c0-13.3-10.7-24-24-24H24c-13.3 0-24 10.7-24 24v248c0 89.5 82.1 160.2 175 140.7 54.4-11.4 98.3-55.4 109.7-109.7 17.4-82.9-37-157.2-112.5-172.2zM209 0c-9.2-.5-17 6.8-17 16v31.6c0 8.5 6.6 15.5 15 15.9 129.4 7 233.4 112 240.9 241.5.5 8.4 7.5 15 15.9 15h32.1c9.2 0 16.5-7.8 16-17C503.4 139.8 372.2 8.6 209 0zm.3 96c-9.3-.7-17.3 6.7-17.3 16.1v32.1c0 8.4 6.5 15.3 14.8 15.9 76.8 6.3 138 68.2 144.9 145.2.8 8.3 7.6 14.7 15.9 14.7h32.2c9.3 0 16.8-8 16.1-17.3-8.4-110.1-96.5-198.2-206.6-206.7z"/> |
|
|
|
830 </svg> |
|
|
|
831 </a> |
|
|
|
832 <a class="icon" href="https://twitter.com/sethmlarson" target="_blank" rel="nofollow noopener noreferrer"> |
|
|
|
833 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> |
|
|
|
834 <title>Twitter</title><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/> |
|
|
|
835 </svg> |
|
|
|
836 </a> |
|
|
|
837 <a class="icon" href="https://github.com/sethmlarson" target="_blank" rel="nofollow noopener noreferrer"> |
|
|
|
838 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"> |
|
|
|
839 <title>GitHub</title><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/> |
|
|
|
840 </svg> |
|
|
|
841 </a> |
|
|
|
842 <a class="icon" href="https://linkedin.com/in/sethmlarson" target="_blank" rel="nofollow noopener noreferrer"> |
|
|
|
843 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"> |
|
|
|
844 <title>LinkedIn</title><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3zM135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5zm282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9V416z"/> |
|
|
|
845 </svg> |
|
|
|
846 </a> |
|
|
|
847 </div> |
|
|
|
848 </div> |
|
|
|
849 </div> |
|
|
|
850 </div> |
|
|
|
851 |
|
|
|
852 <div class="row"> |
|
|
|
853 <div class="col-12"> |
|
|
|
854 <h2 class="blog-title" style="text-align: center">urllib3 raised $15,000 in 2021 (Newsletter #6)</h2> |
|
|
|
855 <p><center>Published 2021-12-29 β <span class="heart">β€&#xFE0E</span> Subscribe for more via <a href="https://tinyletter.com/sethmlarson">the newsletter</a> or <a href="/feed">RSS</a></center></p> |
|
|
|
856 </div> |
|
|
|
857 </div> |
|
|
|
858 <div class="row"> |
|
|
|
859 <div class="col-12"> |
|
|
|
860 <p>Welcome to the 6th urllib3 newsletter, end of 2021 edition! If you'd like to discuss this edition of our newsletter you can<a href="https://discord.gg/urllib3"> join our community Discord</a>.</p> |
|
|
|
861 |
|
|
|
862 <h2>Thanks to our sponsors!</h2> |
|
|
|
863 |
|
|
|
864 <p>This year we received so much support from many different places, people, and organizations. We enter the new year with <strong>$12,254.95 in OpenCollective available for distribution</strong>.</p> |
|
|
|
865 |
|
|
|
866 <p><strong>We're so thankful for everyone who contributed.</strong> Your support means we can fairly pay for people's time and expertise and ensure that PyPI's most downloaded package continues to be secure, up-to-date, and working towards the future of HTTP in Python.</p> |
|
|
|
867 |
|
|
|
868 <p>This large amount of funding means our team is planning on setting up a span of full-time development to focus on closing out v2.0 in addition to continuing to pay contributors both from our team and the community to work on urllib3.</p> |
|
|
|
869 |
|
|
|
870 <h3>Where we received and spent our funding</h3> |
|
|
|
871 |
|
|
|
872 <p>All of these amounts shown below are after fees from payment processing, Coinbase, OpenCollective fiscal hosting, and cryptocurrency gas fees. In short it's the value thatβs available for our team to pay out to contributors. We funnel all of our funds to <a href="https://opencollective.com/urllib3">OpenCollective</a> in order to make payment processing easy for as many individuals as possible.</p> |
|
|
|
873 |
|
|
|
874 <ul> |
|
|
|
875 <li>$8,087.38 from <a href="https://gitcoin.co/grants/65/urllib3">GitCoin Grants</a> ΒΉ</li> |
|
|
|
876 <li>$5,050.00 from <a href="https://tidelift.com/subscription/pkg/pypi-urllib3?utm_source=pypi-urllib3&amp;utm_medium=referral&amp;utm_campaign=enterprise">Tidelift</a> Β²</li> |
|
|
|
877 <li>$1,358.97 from <a href="https://github.com/sponsors/urllib3">GitHub Sponsors</a></li> |
|
|
|
878 <li>$504.00 from <a href="https://opencollective.com/urllib3">OpenCollective contributors</a></li> |
|
|
|
879 <li><strong>$15,000.35</strong> from all sources</li> |
|
|
|
880 </ul> |
|
|
|
881 |
|
|
|
882 <p>Funds were paid out to the following individuals:</p> |
|
|
|
883 |
|
|
|
884 <ul> |
|
|
|
885 <li>$4,075 paid to <a href="https://github.com/sethmlarson">Seth Michael Larson</a></li> |
|
|
|
886 <li>$3,325 paid to <a href="https://github.com/pquentin">Quentin Pradet</a></li> |
|
|
|
887 <li>$1,900 paid to <a href="https://github.com/hramezani">Hasan Ramenzani</a></li> |
|
|
|
888 <li>$140 paid to <a href="https://github.com/davidism">David Lord</a></li> |
|
|
|
889 <li><strong>$9,440</strong> paid in total</li> |
|
|
|
890 </ul> |
|
|
|
891 |
|
|
|
892 <p>ΒΉ Amount from GitCoin is only ETH, DAI, and USDC that were sold for USD. Other currencies that were donated have not been converted to USD yet to avoid paying fees on small amounts.</p> |
|
|
|
893 |
|
|
|
894 <p>Β² Tidelift is paid directly to Seth Larson and Quentin Pradet and isn't subject to OpenCollective fees.</p> |
|
|
|
895 |
|
|
|
896 <h2>Releases and Contributors</h2> |
|
|
|
897 |
|
|
|
898 <p>There were <a href="https://github.com/urllib3/urllib3/releases">5 new releases of urllib3</a> over the past year, two of which contained fixes for security issues <a href="https://github.com/urllib3/urllib3/security/advisories/GHSA-5phf-pp7p-vc2r">CVE-2021-28363</a> and <a href="https://github.com/urllib3/urllib3/security/advisories/GHSA-q2q7-5pp4-w6pg">CVE-2021-33503</a>. Hopefully youβre using the latest 1.26.7 release! We received 197 commits from <a href="https://github.com/urllib3/urllib3/graphs/contributors?from=2021-01-1&amp;to=2021-12-31&amp;type=c">17 unique committers</a> across the year. Thanks to everyone who contributed.</p> |
|
|
|
899 |
|
|
|
900 <h2>Progress towards v2.0</h2> |
|
|
|
901 |
|
|
|
902 <p>The <a href="https://github.com/urllib3/urllib3/milestone/6">v2.0 milestone on GitHub</a> tracks our progress towards the v2.0 release of urllib3. This year our team closed 25 issues in the v2.0 milestone, leaving only <a href="https://github.com/urllib3/urllib3/milestone/6">11 open issues</a> remaining for a v2.0 release. Weβre hopeful that the focus on paying for sustained development time in 2022 will mean a v2.0 release next year.</p> |
|
|
|
903 |
|
|
|
904 <p>Even after v2.0 is released our team plans on continuing bug fix and security support for the v1.26.x release stream thanks to financial support from Tidelift.</p> |
|
|
|
905 |
|
|
|
906 <h2>Type hints case study</h2> |
|
|
|
907 |
|
|
|
908 <p><a href="https://github.com/hramezani">Hasan Ramenzani</a> spent a ton of time working on type hints for the v2.0 branch. This work spanned multiple months and included so many lessons learned and interesting situations that our team <a href="https://sethmlarson.dev/blog/2021-10-18/tests-arent-enough-case-study-after-adding-types-to-urllib3">wrote a case study</a> on the entire experience.</p> |
|
|
|
909 |
|
|
|
910 <h2>Unreasonable effectiveness of investing in open source</h2> |
|
|
|
911 |
|
|
|
912 <p>Quentin Pradet was <a href="https://quentin.pradet.me/blog/i-got-paid-to-work-on-open-source-2.html">paid to work 20 hours on urllib3</a> and once again proved the incredible return on investment that paid open source contributions can be. Over the course of 20 hours Quentin contributed many PRs to urllib3 which resulted in finding a bug in Pythonβs ssl module. Quentin <a href="https://bugs.python.org/issue43522">submitted a bug report</a> to Python which inspired a <a href="https://github.com/openssl/openssl/pull/14856">usability bug fix to OpenSSL</a>. Not bad!</p> |
|
|
|
913 |
|
|
|
914 <h2>PyCascades 2021</h2> |
|
|
|
915 |
|
|
|
916 <p>Seth spoke at <a href="https://2021.pycascades.com/">PyCascades 2021</a> back in February about how the urllib3 team plans on shipping breaking changes in v2.0. You can watch the <a href="https://www.youtube.com/watch?v=o9ESKvkuvXM">recording on Youtube</a>.</p> |
|
|
|
917 |
|
|
|
918 </div> |
|
|
|
919 </div> |
|
|
|
920 <div class="row"> |
|
|
|
921 <div class="col-12"> |
|
|
|
922 <center> |
|
|
|
923 <div class="how-to-subscribe"> |
|
|
|
924 Enjoy this post? <span class="heart">β€&#xFE0E</span> Subscribe for more via <a href="https://tinyletter.com/sethmlarson">the newsletter</a> or <a href="/feed">RSS</a> |
|
|
|
925 </div> |
|
|
|
926 </center> |
|
|
|
927 </div> |
|
|
|
928 </div> |
|
|
|
929 |
|
|
|
930 <div class="row"> |
|
|
|
931 <div class="col-2"></div> |
|
|
|
932 <div class="col-8"><center><small>Built with <a href="https://simplegrid.io" target="_blank" rel="nofollow noopener noreferrer">SimpleGrid</a>, <a href="https://simplegrid.io/" target="_blank" rel="nofollow noopener noreferrer">FontAwesome</a>, <a href="https://flask.palletsprojects.com" target="_blank" rel="nofollow noopener noreferrer">Flask</a>, and <a href="https://github.com/sethmlarson/sethmlarson.dev" target="_blank" rel="nofollow noopener noreferrer">more</a>.</small></center></div> |
|
|
|
933 <div class="col-2"></div> |
|
|
|
934 </div> |
|
|
|
935 </div> |
|
|
|
936 |
|
|
|
937 <!-- Google Analytics --> |
|
|
|
938 <script async src="https://www.googletagmanager.com/gtag/js?id=G-C3VD7T243W"></script> |
|
|
|
939 <script> |
|
|
|
940 window.dataLayer = window.dataLayer || []; |
|
|
|
941 function gtag(){dataLayer.push(arguments);} |
|
|
|
942 gtag('js', new Date()); |
|
|
|
943 gtag('config', 'G-C3VD7T243W'); |
|
|
|
944 </script> |
|
|
|
945 </body> |
|
|
|
946 </html></content> |
|
|
|
947 </entry> |
|
|
|
948 <entry xml:base="http://sethmlarson.dev/feed"> |
|
|
|
949 <title type="text">Experimental APIs in Python 3.10 and the future of trust stores</title> |
|
|
|
950 <id>http://sethmlarson.dev/blog/experimental-python-3.10-apis-and-trust-stores?date=2021-11-27</id> |
|
|
|
951 <updated>2021-11-27T00:00:00Z</updated> |
|
|
|
952 <published>2021-11-27T00:00:00Z</published> |
|
|
|
953 <link href="http://sethmlarson.dev/blog/experimental-python-3.10-apis-and-trust-stores?date=2021-11-27" /> |
|
|
|
954 <author> |
|
|
|
955 <name>Seth Michael Larson</name> |
|
|
|
956 </author> |
|
|
|
957 <content type="html"><!DOCTYPE html> |
|
|
|
958 <html lang="en"> |
|
|
|
959 <head> |
|
|
|
960 <meta charset="utf-8"> |
|
|
|
961 <title>Experimental APIs in Python 3.10 and the future of trust stores</title> |
|
|
|
962 <meta name="description" content="Blogging about Python and the Internet"> |
|
|
|
963 <meta name="keywords" content="blog python open source http networking security"> |
|
|
|
964 <meta name="author" content="Seth Michael Larson"> |
|
|
|
965 <meta name="viewport" content="width=device-width, initial-scale=1"> |
|
|
|
966 <meta name="format-detection" content="telephone=no"/> |
|
|
|
967 <link rel="alternate" type="application/rss+xml" title="RSS Feed" href="/feed"/> |
|
|
|
968 <link rel="icon" href="/static/favicon.ico"> |
|
|
|
969 <link rel="stylesheet" href="/static/style.css"> |
|
|
|
970 |
|
|
|
971 <meta property="og:site_name" content="Seth Michael Larson"/> |
|
|
|
972 <meta property="og:author" content="Seth Michael Larson"/> |
|
|
|
973 <meta property="og:type" content="article"/> |
|
|
|
974 <meta property="og:title" content="Experimental APIs in Python 3.10 and the future of trust stores"/> |
|
|
|
975 <meta property="og:description" content="β οΈ The APIs mentioned below aren&#39;t documented in the Python docs or release notes and are experimental. I recommend not using them until they are stable. |
|
|
|
976 |
|
|
|
977 In Python 3.10.0 there were a few new APIs..."/> |
|
|
|
978 <meta property="og:image" content="http://sethmlarson.dev/static/avatar.jpeg"/> |
|
|
|
979 <meta name="twitter:card" content="summary"/> |
|
|
|
980 <meta name="twitter:site" content="@sethmlarson"/> |
|
|
|
981 <meta name="twitter:creator" content="@sethmlarson"/> |
|
|
|
982 <meta name="twitter:title" content="Experimental APIs in Python 3.10 and the future of trust stores"/> |
|
|
|
983 <meta name="twitter:description" content="β οΈ The APIs mentioned below aren&#39;t documented in the Python docs or release notes and are experimental. I recommend not using them until they are stable. |
|
|
|
984 |
|
|
|
985 In Python 3.10.0 there were a few new APIs..."/> |
|
|
|
986 <meta property="og:image" content="http://sethmlarson.dev/static/avatar.jpeg"/> |
|
|
|
987 |
|
|
|
988 </head> |
|
|
|
989 <body> |
|
|
|
990 <div class="container"> |
|
|
|
991 <div class="row"> |
|
|
|
992 <div class="col-6"> |
|
|
|
993 <center> |
|
|
|
994 <h1 style="margin-bottom: 0.1em; font-size: 1.8em;">Seth Michael Larson</h1> |
|
|
|
995 <span style="font-style: italic;">Blogging about Python and the Internet</span> |
|
|
|
996 </center> |
|
|
|
997 </div> |
|
|
|
998 <div class="col-6"> |
|
|
|
999 <div class="navbar-outer"> |
|
|
|
1000 <div class="navbar-inner"> |
|
|
|
1001 <a class="icon" href="/about"> |
|
|
|
1002 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"> |
|
|
|
1003 <title>About</title><path d="M528 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h480c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-352 96c35.3 0 64 28.7 64 64s-28.7 64-64 64-64-28.7-64-64 28.7-64 64-64zm112 236.8c0 10.6-10 19.2-22.4 19.2H86.4C74 384 64 375.4 64 364.8v-19.2c0-31.8 30.1-57.6 67.2-57.6h5c12.3 5.1 25.7 8 39.8 8s27.6-2.9 39.8-8h5c37.1 0 67.2 25.8 67.2 57.6v19.2zM512 312c0 4.4-3.6 8-8 8H360c-4.4 0-8-3.6-8-8v-16c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16zm0-64c0 4.4-3.6 8-8 8H360c-4.4 0-8-3.6-8-8v-16c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16zm0-64c0 4.4-3.6 8-8 8H360c-4.4 0-8-3.6-8-8v-16c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16z"/> |
|
|
|
1004 </svg> |
|
|
|
1005 </a> |
|
|
|
1006 <a class="icon" href="/blog"> |
|
|
|
1007 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> |
|
|
|
1008 <title>Blog</title><path d="M172.2 226.8c-14.6-2.9-28.2 8.9-28.2 23.8V301c0 10.2 7.1 18.4 16.7 22 18.2 6.8 31.3 24.4 31.3 45 0 26.5-21.5 48-48 48s-48-21.5-48-48V120c0-13.3-10.7-24-24-24H24c-13.3 0-24 10.7-24 24v248c0 89.5 82.1 160.2 175 140.7 54.4-11.4 98.3-55.4 109.7-109.7 17.4-82.9-37-157.2-112.5-172.2zM209 0c-9.2-.5-17 6.8-17 16v31.6c0 8.5 6.6 15.5 15 15.9 129.4 7 233.4 112 240.9 241.5.5 8.4 7.5 15 15.9 15h32.1c9.2 0 16.5-7.8 16-17C503.4 139.8 372.2 8.6 209 0zm.3 96c-9.3-.7-17.3 6.7-17.3 16.1v32.1c0 8.4 6.5 15.3 14.8 15.9 76.8 6.3 138 68.2 144.9 145.2.8 8.3 7.6 14.7 15.9 14.7h32.2c9.3 0 16.8-8 16.1-17.3-8.4-110.1-96.5-198.2-206.6-206.7z"/> |
|
|
|
1009 </svg> |
|
|
|
1010 </a> |
|
|
|
1011 <a class="icon" href="https://twitter.com/sethmlarson" target="_blank" rel="nofollow noopener noreferrer"> |
|
|
|
1012 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> |
|
|
|
1013 <title>Twitter</title><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/> |
|
|
|
1014 </svg> |
|
|
|
1015 </a> |
|
|
|
1016 <a class="icon" href="https://github.com/sethmlarson" target="_blank" rel="nofollow noopener noreferrer"> |
|
|
|
1017 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"> |
|
|
|
1018 <title>GitHub</title><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/> |
|
|
|
1019 </svg> |
|
|
|
1020 </a> |
|
|
|
1021 <a class="icon" href="https://linkedin.com/in/sethmlarson" target="_blank" rel="nofollow noopener noreferrer"> |
|
|
|
1022 <svg width="2em" height="2em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"> |
|
|
|
1023 <title>LinkedIn</title><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3zM135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5zm282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9V416z"/> |
|
|
|
1024 </svg> |
|
|
|
1025 </a> |
|
|
|
1026 </div> |
|
|
|
1027 </div> |
|
|
|
1028 </div> |
|
|
|
1029 </div> |
|
|
|
1030 |
|
|
|
1031 <div class="row"> |
|
|
|
1032 <div class="col-12"> |
|
|
|
1033 <h2 class="blog-title" style="text-align: center">Experimental APIs in Python 3.10 and the future of trust stores</h2> |
|
|
|
1034 <p><center>Published 2021-11-27 β <span class="heart">β€&#xFE0E</span> Subscribe for more via <a href="https://tinyletter.com/sethmlarson">the newsletter</a> or <a href="/feed">RSS</a></center></p> |
|
|
|
1035 </div> |
|
|
|
1036 </div> |
|
|
|
1037 <div class="row"> |
|
|
|
1038 <div class="col-12"> |
|
|
|
1039 <p><strong>β οΈ The APIs mentioned below aren't documented in the Python docs or release notes and are experimental. I recommend not using them until they are stable.</strong></p> |
|
|
|
1040 |
|
|
|
1041 <p>In Python 3.10.0 there were a few new APIs added to the <code>ssl</code> module related to certificate chains that weren't listed in the <a href="https://docs.python.org/3/whatsnew/3.10.html">Python 3.10 release notes</a> due to being experimental. I discovered these APIs because I follow the <code>ssl</code> module closely as any changes to the module will likely create a feature request or additional test case for urllib3.</p> |
|
|
|
1042 |
|
|
|
1043 <p>Let's see the new APIs in action and how their addition could mean a bright future for <a href="https://stackoverflow.com/a/318450/5763213">trust stores</a> in Python:</p> |
|
|
|
1044 |
|
|
|
1045 <h2>Using the new APIs</h2> |
|
|
|
1046 |
|
|
|
1047 <p>To see these APIs in action let's create a typical TLS connection to <code>example.com</code>:</p> |
|
|
|
1048 |
|
|
|
1049 <div class="codehilite"><pre><span></span><code><span class="o">&gt;&gt;&gt;</span> <span class="kn">import</span> <span class="nn">socket</span> |
|
|
|
1050 <span class="o">&gt;&gt;&gt;</span> <span class="kn">import</span> <span class="nn">ssl</span> |
|
|
|
1051 <span class="o">&gt;&gt;&gt;</span> |
|
|
|
1052 <span class="o">&gt;&gt;&gt;</span> <span class="n">ctx</span> <span class="o">=</span> <span class="n">ssl</span><span class="o">.</span><span class="n">create_default_context</span><span class="p">()</span> |
|
|
|
1053 <span class="o">&gt;&gt;&gt;</span> <span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">create_connection</span><span class="p">((</span><span class="s2">&quot;example.com&quot;</span><span class="p">,</span> <span class="mi">443</span><span class="p">))</span> |
|
|
|
1054 <span class="o">&gt;&gt;&gt;</span> <span class="n">sock</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">.</span><span class="n">wrap_socket</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">server_hostname</span><span class="o">=</span><span class="s2">&quot;example.com&quot;</span><span class="p">)</span> |
|
|
|
1055 <span class="o">&gt;&gt;&gt;</span> |
|
|
|
1056 <span class="o">&gt;&gt;&gt;</span> <span class="n">sock</span> |
|
|
|
1057 <span class="o">&lt;</span><span class="n">ssl</span><span class="o">.</span><span class="n">SSLSocket</span> <span class="n">fd</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">family</span><span class="o">=</span><span class="n">AddressFamily</span><span class="o">.</span><span class="n">AF_INET6</span><span class="p">,</span> <span class="o">...&gt;</span> |
|
|
|
1058 </code></pre></div> |
|
|
|
1059 |
|
|
|
1060 <p>Nothing out of the ordinary here yet. Now having looked at the PR that added these APIs, they're not yet available on an <code>SSLSocket</code> object directly. Instead they're exposed in <a href="https://docs.python.org/3/library/ssl.html#ssl.SSLObject"><code>ssl.SSLObject</code></a> which is a reduced-scope variant of <code>SSLSocket</code> meant to be used as an interface for TLS with memory buffers.</p> |
|
|
|
1061 |
|
|
|
1062 <p>But we can access the internal <code>SSLObject</code> instance on an <code>SSLSocket</code> via the <code>_sslobj</code> property:</p> |
|
|
|
1063 |
|
|
|
1064 <div class="codehilite"><pre><span></span><code><span class="o">&gt;&gt;&gt;</span> <span class="n">sslobj</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">_sslobj</span> |
|
|
|
1065 <span class="o">&gt;&gt;&gt;</span> <span class="n">sslobj</span> |
|
|
|
1066 <span class="o">&lt;</span><span class="n">_ssl</span><span class="o">.</span><span class="n">_SSLSocket</span> <span class="nb">object</span> <span class="n">at</span> <span class="mh">0x7f167d8a5c40</span><span class="o">&gt;</span> |
|
|
|
1067 </code></pre></div> |
|
|
|
1068 |
|
|
|
1069 <p>From here we can start poking around with the new certificate APIs. The following are the new APIs I know about:</p> |
|
|
|
1070 |
|
|
|
1071 <div class="codehilite"><pre><span></span><code><span class="kn">import</span> <span class="nn">_ssl</span> |
|
|
|
1072 |
|
|
|
1073 <span class="n">_ssl</span><span class="o">.</span><span class="n">ENCODING_PEM</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># enum</span> |
|
|
|
1074 <span class="n">_ssl</span><span class="o">.</span><span class="n">ENCODING_DER</span> <span class="o">=</span> <span class="mi">2</span> <span class="c1"># enum</span> |
|
|
|
1075 |
|
|
|
1076 <span class="n">_ssl</span><span class="o">.</span><span class="n">Certificate</span> <span class="c1"># class</span> |
|
|
|
1077 |
|
|
|
1078 <span class="c1"># see: SSLSocket.getpeercert(binary_form=True)</span> |
|
|
|
1079 <span class="n">_ssl</span><span class="o">.</span><span class="n">Certificate</span><span class="o">.</span><span class="n">public_bytes</span><span class="p">(</span><span class="n">encoding</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Union</span><span class="p">[</span><span class="nb">bytes</span><span class="p">,</span> <span class="nb">str</span><span class="p">]</span> |
|
|
|
1080 |
|
|
|
1081 <span class="c1"># see: SSLSocket.getpeercert(binary_form=False)</span> |
|
|
|
1082 <span class="n">_ssl</span><span class="o">.</span><span class="n">Certificate</span><span class="o">.</span><span class="n">get_info</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Any</span><span class="p">]</span> |
|
|
|
1083 |
|
|
|
1084 <span class="n">ssl</span><span class="o">.</span><span class="n">SSLObject</span><span class="o">.</span><span class="n">get_unverified_chain</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">_ssl</span><span class="o">.</span><span class="n">Certificate</span><span class="p">]</span> |
|
|
|
1085 <span class="n">ssl</span><span class="o">.</span><span class="n">SSLObject</span><span class="o">.</span><span class="n">get_verified_chain</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">_ssl</span><span class="o">.</span><span class="n">Certificate</span><span class="p">]</span> |
|
|
|
1086 </code></pre></div> |
|
|
|
1087 |
|
|
|
1088 <p>If we try using these APIs we can get the following information:</p> |
|
|
|
1089 |
|
|
|
1090 <div class="codehilite"><pre><span></span><code><span class="o">&gt;&gt;&gt;</span> <span class="n">unverified_chain</span> <span class="o">=</span> <span class="n">sslobj</span><span class="o">.</span><span class="n">get_unverified_chain</span><span class="p">()</span> |
|
|
|
1091 <span class="o">&gt;&gt;&gt;</span> <span class="n">verified_chain</span> <span class="o">=</span> <span class="n">sslobj</span><span class="o">.</span><span class="n">get_verified_chain</span><span class="p">()</span> |
|
|
|
1092 |
|
|
|
1093 <span class="c1"># In our case, the &#39;unverified_chain&#39; and &#39;verified_chain&#39;</span> |
|
|
|
1094 <span class="c1"># are the same we&#39;ll discuss the difference below.</span> |
|
|
|
1095 <span class="o">&gt;&gt;&gt;</span> <span class="k">assert</span> <span class="n">unverified_chain</span> <span class="o">==</span> <span class="n">verified_chain</span> |
|
|
|
1096 |
|
|
|
1097 <span class="c1"># The chains go in order from leaf -&gt; root.</span> |
|
|
|
1098 <span class="c1"># verified_chain[0] is the same as sock.getpeercert()</span> |
|
|
|
1099 <span class="o">&gt;&gt;&gt;</span> <span class="k">assert</span> <span class="n">sock</span><span class="o">.</span><span class="n">getpeercert</span><span class="p">(</span><span class="kc">True</span><span class="p">)</span> <span class="o">==</span> \ |
|
|
|
1100 <span class="n">verified_chain</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">public_bytes</span><span class="p">(</span><span class="n">_ssl</span><span class="o">.</span><span class="n">ENCODING_DER</span><span class="p">)</span> |
|
|
|
1101 |
|
|
|
1102 <span class="c1"># The individual certificates in the chain have two methods:</span> |
|
|
|
1103 <span class="c1"># .get_info() and .public_bytes(encoding)</span> |
|
|
|
1104 <span class="o">&gt;&gt;&gt;</span> <span class="n">verified_chain</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">public_bytes</span><span class="p">(</span><span class="n">_ssl</span><span class="o">.</span><span class="n">ENCODING_PEM</span><span class="p">)</span> |
|
|
|
1105 <span class="s1">&#39;-----BEGIN CERTIFICATE-----</span><span class="se">\n</span><span class="s1">MIIG1TC ...&#39;</span> |
|
|
|
1106 |
|
|
|
1107 <span class="c1"># Using _ssl.ENCODING_DER is the same as socket.getpeercert(True)</span> |
|
|
|
1108 <span class="o">&gt;&gt;&gt;</span> <span class="n">verified_chain</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">public_bytes</span><span class="p">(</span><span class="n">_ssl</span><span class="o">.</span><span class="n">ENCODING_DER</span><span class="p">)</span> |
|
|
|
1109 <span class="sa">b</span><span class="s1">&#39;0</span><span class="se">\x82\x06\xd5</span><span class="s1">0</span><span class="se">\x82</span><span class="s1"> ... </span><span class="se">\x05\x0f\xe3</span><span class="s1">E#</span><span class="se">\xc0</span><span class="s1">d_&#39;</span> |
|
|
|
1110 |
|
|
|
1111 <span class="c1"># _ssl.Certificate.get_info() is the same as sock.getpeercert(False)</span> |
|
|
|
1112 <span class="o">&gt;&gt;&gt;</span> <span class="n">verified_chain</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">get_info</span><span class="p">()</span> |
|
|
|
1113 <span class="p">{</span> |
|
|
|
1114 <span class="s2">&quot;OCSP&quot;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&quot;http://ocsp.digicert.com&quot;</span><span class="p">],</span> |
|
|
|
1115 <span class="s2">&quot;caIssuers&quot;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&quot;http://cacerts.digicert.com/...&quot;</span><span class="p">],</span> |
|
|
|
1116 <span class="s2">&quot;crlDistributionPoints&quot;</span><span class="p">:</span> <span class="p">[</span> |
|
|
|
1117 <span class="s2">&quot;http://crl3.digicert.com/...crl&quot;</span><span class="p">,</span> |
|
|
|
1118 <span class="s2">&quot;http://crl4.digicert.com/...crl&quot;</span> |
|
|
|
1119 <span class="p">],</span> |
|
|
|
1120 <span class="s2">&quot;issuer&quot;</span><span class="p">:</span> <span class="p">[</span> |
|
|
|
1121 <span class="p">[[</span><span class="s2">&quot;countryName&quot;</span><span class="p">,</span> <span class="s2">&quot;US&quot;</span><span class="p">]],</span> |
|
|
|
1122 <span class="p">[[</span><span class="s2">&quot;organizationName&quot;</span><span class="p">,</span> <span class="s2">&quot;DigiCert Inc&quot;</span><span class="p">]],</span> |
|
|
|
1123 <span class="p">[[</span><span class="s2">&quot;commonName&quot;</span><span class="p">,</span> <span class="s2">&quot;DigiCert TLS RSA SHA256 2020 CA1&quot;</span><span class="p">]]</span> |
|
|
|
1124 <span class="p">],</span> |
|
|
|
1125 <span class="s2">&quot;notAfter&quot;</span><span class="p">:</span> <span class="s2">&quot;Dec 25 23:59:59 2021 GMT&quot;</span><span class="p">,</span> |
|
|
|
1126 <span class="s2">&quot;notBefore&quot;</span><span class="p">:</span> <span class="s2">&quot;Nov 24 00:00:00 2020 GMT&quot;</span><span class="p">,</span> |
|
|
|
1127 <span class="s2">&quot;serialNumber&quot;</span><span class="p">:</span> <span class="s2">&quot;0FBE08B0854D05738AB0CCE1C9AFEEC9&quot;</span><span class="p">,</span> |
|
|
|
1128 <span class="s2">&quot;subject&quot;</span><span class="p">:</span> <span class="p">[</span> |
|
|
|
1129 <span class="p">[[</span><span class="s2">&quot;countryName&quot;</span><span class="p">,</span> <span class="s2">&quot;US&quot;</span><span class="p">]],</span> |
|
|
|
1130 <span class="p">[[</span><span class="s2">&quot;stateOrProvinceName&quot;</span><span class="p">,</span> <span class="s2">&quot;California&quot;</span><span class="p">]],</span> |
|
|
|
1131 <span class="p">[[</span><span class="s2">&quot;localityName&quot;</span><span class="p">,</span> <span class="s2">&quot;Los Angeles&quot;</span><span class="p">]],</span> |
|
|
|
1132 <span class="p">[[</span><span class="s2">&quot;organizationName&quot;</span><span class="p">,</span> <span class="s2">&quot;...&quot;</span><span class="p">]],</span> |
|
|
|
1133 <span class="p">[[</span><span class="s2">&quot;commonName&quot;</span><span class="p">,</span> <span class="s2">&quot;www.example.org&quot;</span><span class="p">]]</span> |
|
|
|
1134 <span class="p">],</span> |
|
|
|
1135 <span class="s2">&quot;subjectAltName&quot;</span><span class="p">:</span> <span class="p">[</span> |
|
|
|
1136 <span class="p">[</span><span class="s2">&quot;DNS&quot;</span><span class="p">,</span> <span class="s2">&quot;www.example.org&quot;</span><span class="p">],</span> |
|
|
|
1137 <span class="p">[</span><span class="s2">&quot;DNS&quot;</span><span class="p">,</span> <span class="s2">&quot;example.com&quot;</span><span class="p">],</span> |
|
|
|
1138 <span class="p">[</span><span class="s2">&quot;DNS&quot;</span><span class="p">,</span> <span class="s2">&quot;example.edu&quot;</span><span class="p">],</span> |
|
|
|
1139 <span class="p">[</span><span class="s2">&quot;DNS&quot;</span><span class="p">,</span> <span class="s2">&quot;example.net&quot;</span><span class="p">],</span> |
|
|
|
1140 <span class="p">[</span><span class="s2">&quot;DNS&quot;</span><span class="p">,</span> <span class="s2">&quot;example.org&quot;</span><span class="p">],</span> |
|
|
|
1141 <span class="p">[</span><span class="s2">&quot;DNS&quot;</span><span class="p">,</span> <span class="s2">&quot;www.example.com&quot;</span><span class="p">],</span> |
|
|
|
1142 <span class="p">[</span><span class="s2">&quot;DNS&quot;</span><span class="p">,</span> <span class="s2">&quot;www.example.edu&quot;</span><span class="p">],</span> |
|
|
|
1143 <span class="p">[</span><span class="s2">&quot;DNS&quot;</span><span class="p">,</span> <span class="s2">&quot;www.example.net&quot;</span><span class="p">]</span> |
|
|
|
1144 <span class="p">],</span> |
|
|
|
1145 <span class="s2">&quot;version&quot;</span><span class="p">:</span> <span class="mi">3</span> |
|
|
|
1146 <span class="p">}</span> |
|
|
|
1147 </code></pre></div> |
|
|
|
1148 |
|
|
|
1149 <h3>What is new with these APIs?</h3> |
|
|
|
1150 |
|
|
|
1151 <p>Before Python 3.10 the only certificate information we could gather from an <code>SSLSocket</code> was from the leaf certificate via the <code>getpeercert()</code> method. The complete certificate chain that was sent during the handshake wouldn't be available from Python. This meant that only the leaf certificate could be used in trust decisions from applications.</p> |
|
|
|
1152 |
|
|
|
1153 <p>With these new APIs applications and libraries can make trust decisions with the entire cert chain. <strong>Root CA pinning and using systems besides OpenSSL for trust decisions are now possible in Python! π</strong></p> |
|
|
|
1154 |
|
|
|
1155 <p>To use a separate API for verifying cert chains we can configure an <code>ssl.SSLContext</code> to not verify certificates during the handshake with <code>SSLContext.verify_mode = ssl.CERT_NONE</code> flag and instead use the <code>unverified_certificates()</code> method capture to forward all certificates to the separate API for verifying certs:</p> |
|
|
|
1156 |
|
|
|
1157 <div class="codehilite"><pre><span></span><code><span class="kn">import</span> <span class="nn">ssl</span> |
|
|
|
1158 |
|
|
|
1159 <span class="c1"># Disable cert verification (enabled by default)</span> |
|
|
|
1160 <span class="n">ctx</span> <span class="o">=</span> <span class="n">ssl</span><span class="o">.</span><span class="n">create_default_context</span><span class="p">()</span> |
|
|
|
1161 <span class="n">ctx</span><span class="o">.</span><span class="n">check_hostname</span> <span class="o">=</span> <span class="kc">False</span> |
|
|
|
1162 <span class="n">ctx</span><span class="o">.</span><span class="n">verify_mode</span> <span class="o">=</span> <span class="n">ssl</span><span class="o">.</span><span class="n">CERT_NONE</span> |
|
|
|
1163 |
|
|
|
1164 <span class="c1"># Handshake as normal, still set `server_hostname` for SNI</span> |
|
|
|
1165 <span class="n">sock</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">.</span><span class="n">wrap_socket</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">server_hostname</span><span class="o">=</span><span class="s2">&quot;example.com&quot;</span><span class="p">)</span> |
|
|
|
1166 <span class="n">cert_chain</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">_sslobj</span><span class="o">.</span><span class="n">unverified_chain</span><span class="p">()</span> |
|
|
|
1167 |
|
|
|
1168 <span class="c1"># Use a different API to verify certificates:</span> |
|
|
|
1169 <span class="n">verify_cert_chain_api</span><span class="p">(</span><span class="n">cert_chain</span><span class="p">)</span> |
|
|
|
1170 </code></pre></div> |
|
|
|
1171 |
|
|
|
1172 <h3>Difference between <code>verified_chain()</code> and <code>unverified_chain()</code> methods</h3> |
|
|
|
1173 |
|
|
|
1174 <p>Despite similar names and return types, the <code>verified_chain()</code> and <code>unverified_chain()</code> methods have two distinct uses. The <code>verified_chain()</code> method uses OpenSSL's <code>SSL_get0_verified_chain</code> function. <a href="https://manpages.debian.org/testing/libssl-doc/SSL_get0_verified_chain.3ssl.en.html">The documentation of this function</a> says that it returns "the <strong>verified</strong> certificate chain of the peer including the peer's end entity certificate". The unverified_chain() method uses the <code>SSL_get_peer_cert_chain()</code> OpenSSL function which returns a certificate chain that is <strong>not verified</strong>.</p> |
|
|
|
1175 |
|
|
|
1176 <p>The difference between a verified and unverified chain is whether the chain is the minimal number of certificates between the target entity certificate and a trust anchor in the trust store. All certificates within a verified chain are valid, unexpired, and (as far as OpenSSL knows) not revoked. An unverified chain can include certificates that arenβt valid, are expired or revoked, or simply not necessary to create a chain of trust.</p> |
|
|
|
1177 |
|
|
|
1178 <p>For example if the server provides 4 certificates during the TLS handshake (named L, A, B, and C) where C is in the trust store as a trust anchor and A and B are both intermediate certificates signed by C. The L certificate is the leaf certificate being used by the server and is signed by A. Hereβs an ASCII-art diagram for the above situation:</p> |
|
|
|
1179 |
|
|
|
1180 <pre><code> βββββββββ βββββββββ |
|
|
|
1181 β β β β |
|
|
|
1182 β β β β |
|
|
|
1183 β A βββββΊ L+ β |
|
|
|
1184 βββββββββ β β β β |
|
|
|
1185 β βββββΊ β β β |
|
|
|
1186 β β βββββββββ βββββββββ |
|
|
|
1187 β C* β |
|
|
|
1188 β β βββββββββ |
|
|
|
1189 β βββββΊ β Legend |
|
|
|
1190 βββββββββ β β ββββββββββ |
|
|
|
1191 β B β ββΊ Signs |
|
|
|
1192 β β + Entity/leaf |
|
|
|
1193 β β * Trusted |
|
|
|
1194 βββββββββ |
|
|
|
1195 </code></pre> |
|
|
|
1196 |
|
|
|
1197 <p>This means that B is not necessary to create a chain of trust for the handshake. In this case <code>verified_chain()</code> method would include L, A, and C and the <code>unverified_chain()</code> method would return L, A, B, and C.</p> |
|
|
|
1198 |
|
|
|
1199 <h3>Why are OS trust stores better?</h3> |
|
|
|
1200 |
|
|
|
1201 <p>Why are OS trust stores superior to OpenSSL on platforms where these APIs are available? OS trust store APIs include many more features that are automatically handled in the background that make the experience better for both application developers and system operators.</p> |
|
|
|
1202 |
|
|
|
1203 <p>Windows automatically downloads missing intermediate certificates when theyβre detected and keeps the trust store up to date automatically via the Windows update process. This means that a new installation of Windows will still be able to make TLS handshakes without first manually downloading or updating certificates.</p> |
|
|
|
1204 |
|
|
|
1205 <p>Windows and macOS both check certificate revocation lists (CRL) for certificates in a chain. If youβre using CRLs with OpenSSL youβll have to implement the functionality yourself instead of getting it for free from the OS.</p> |
|
|
|
1206 |
|
|
|
1207 <p>For full details on these APIs you can read the documentation on <a href="https://docs.microsoft.com/en-us/windows/win32/secauthn/secure-channel">Secure Channel</a> and <a href="https://docs.microsoft.com/en-us/windows/win32/seccrypto/cryptography-functions#certificate-trust-list-functions">CryptoAPI</a> for Windows and <a href="https://developer.apple.com/documentation/security/secure_transport">Secure Transport</a> and <a href="https://developer.apple.com/documentation/security/certificate_key_and_trust_services/trust?language=objc">Security framework</a> for macOS.</p> |
|
|
|
1208 |
|
|
|
1209 <h2>Whatβs next for trust stores in Python?</h2> |
|
|
|
1210 |
|
|
|
1211 <p>Python's <code>ssl</code> module is married to the OpenSSL API in multiple places. Even on Windows and macOS Python ships with its own version of OpenSSL for each platform to use with the <code>ssl</code> module. Because of this Python's trust store APIs are similarly OpenSSL-centric, allowing you to specify "<a href="https://docs.python.org/3/library/ssl.html#ssl.SSLContext.load_verify_locations">verify locations</a>" as a file, directory, or in-memory certificate data.</p> |
|
|
|
1212 |
|
|
|
1213 <p>Non-Python native applications are unlikely to use this method, instead they defer to the operating system's trust store implementation to verify certificates, establish a TLS connection, or send an HTTP request over HTTPS.</p> |
|
|
|
1214 |
|
|
|
1215 <h3>Prior art in PEP 543</h3> |
|
|
|
1216 |
|
|
|
1217 <p><a href="https://www.python.org/dev/peps/pep-0543">PEP 543</a> put forward a proposal for new TLS APIs for Python which are implementation agnostic and not tied to OpenSSL to open the door for alternate TLS implementations. The PEP contains a lot of discussion about trust stores and wanted to credit <a href="https://github.com/Lukasa">Cory Benfield</a> and <a href="https://www.python.org/dev/peps/pep-0543/#toc-entry-27">all the authors and reviewers</a> for their work on the PEP.</p> |
|
|
|
1218 |
|
|
|
1219 <p>The <a href="https://www.python.org/dev/peps/pep-0543/#problems">problems listed in the PEP</a> are mostly in the same state as they were in 2016 when the PEP was proposed. I recommend reading the PEP for historical context.</p> |
|
|
|
1220 |
|
|
|
1221 <h3>The end of certifi</h3> |
|
|
|
1222 |
|
|
|
1223 <p><a href="https://github.com/certifi/python-certifi">Certifi</a> is a <a href="https://hg.mozilla.org/releases/mozilla-beta/file/tip/security/nss/lib/ckfw/builtins/certdata.txt">repackaging of Mozillaβs CA bundle</a> meant to be a stopgap for the problem on Windows and macOS not having a single CA bundle to configure OpenSSL to use. Certificates are bundled into the certifi package and then a single API, <code>certifi.where()</code> will return the location on disk of the unbundled certifi certificates, typically somewhere within your <code>venv/lib/python/.../site-packages/...</code> directory.</p> |
|
|
|
1224 |
|
|
|
1225 <p>This seems like a fine solution at first, but from the perspective of a system operator this is a nightmare. You now have tons of different CA bundles that are tough to track, usually per-application, and can easily get out of date. This is another big win when all applications use a single OS trust store instead of one trust store per application.</p> |
|
|
|
1226 |
|
|
|
1227 <p>A small experimental package written by Python core developer <a href="https://github.com/tiran">Christian Heimes</a> tries to solve this problem. The package <a href="https://github.com/tiran/certifi-system-store">certifi-system-store</a> will rewrite the dist-info of the certifi package to point to the "actual" OS trust store instead of certifi's bundled trust store. However this solution is experimental, requires running a command after installation, and only works on Linux which is a platform that's already covered by not using certifi and using <code>ssl.create_default_context()</code> instead.</p> |
|
|
|
1228 |
|
|
|
1229 <h3>The future is OS trust stores</h3> |
|
|
|
1230 |
|
|
|
1231 <p>The APIs mentioned above will likely stabilize and be available in a future Python version. My hope is before Python 3.10+ becomes pervasive there will be an effort to implement OS trust stores such that they can be used seamlessly by libraries and applications. We have many developers (myself included) that would be interested in helping make certificate verification better for everyone in our ecosystem.</p> |
|
|
|
1232 |
|
|
|
1233 </div> |
|
|
|
1234 </div> |
|
|
|
1235 <div class="row"> |
|
|
|
1236 <div class="col-12"> |
|
|
|
1237 <center> |
|
|
|
1238 <div class="how-to-subscribe"> |
|
|
|
1239 Enjoy this post? <span class="heart">β€&#xFE0E</span> Subscribe for more via <a href="https://tinyletter.com/sethmlarson">the newsletter</a> or <a href="/feed">RSS</a> |
|
|
|
1240 </div> |
|
|
|
1241 </center> |
|
|
|
1242 </div> |
|
|
|
1243 </div> |
|
|
|
1244 |
|
|
|
1245 <div class="row"> |
|
|
|
1246 <div class="col-2"></div> |
|
|
|
1247 <div class="col-8"><center><small>Built with <a href="https://simplegrid.io" target="_blank" rel="nofollow noopener noreferrer">SimpleGrid</a>, <a href="https://simplegrid.io/" target="_blank" rel="nofollow noopener noreferrer">FontAwesome</a>, <a href="https://flask.palletsprojects.com" target="_blank" rel="nofollow noopener noreferrer">Flask</a>, and <a href="https://github.com/sethmlarson/sethmlarson.dev" target="_blank" rel="nofollow noopener noreferrer">more</a>.</small></center></div> |
|
|
|
1248 <div class="col-2"></div> |
|
|
|
1249 </div> |
|
|
|
1250 </div> |
|
|
|
1251 |
|
|
|
1252 <!-- Google Analytics --> |
|
|
|
1253 <script async src="https://www.googletagmanager.com/gtag/js?id=G-C3VD7T243W"></script> |
|
|
|
1254 <script> |
|
|
|
1255 window.dataLayer = window.dataLayer || []; |
|
|
|
1256 function gtag(){dataLayer.push(arguments);} |
|
|
|
1257 gtag('js', new Date()); |
|
|
|
1258 gtag('config', 'G-C3VD7T243W'); |
|
|
|
1259 </script> |
|
|
|
1260 </body> |
|
|
|
1261 </html></content> |
|
|
|
1262 </entry> |
|
|
|
1263 </feed> |
|